复习this及其绑定

288 阅读3分钟

this

  • this是函数在运行的时候,函数体内部自动生成的一个对象,只能在函数体内部使用。总的来说就是函数运行时所在的环境对象。
  • this 永远指向最后调用它的那个对象,this 永远指向最后调用它的那个对象,this 永远指向最后调用它的那个对象。
  • 回调函数中的this默认是指向window的,因为本质上是在函数内callback,并没有.操作符前的对象调用。
用法一 函数调用
  • 这是函数的最通常用法,属于全局性调用,因此this就代表全局对象。
    var x = 1;
    function test() {
      console.log(this.x);
    }
    test();  // 1
    
用法二 作为对象的方法调用
  • 函数还作为某个对象的方法调用,这时this就指这个上级对象。
    function test() {
      console.log(this.x);
    }
    
    var obj = {};
    obj.x = 1;
    obj.m = test;
    
    obj.m(); // 1
    
用法三 构造函数
  • 构造函数,就是通过这个函数,可以生成一个新对象。这时,this就指这个新对象。
    function test () {
       this.x = 1; // 让新对象的x属性变为1
    }
    var obj = new test();
    obj.x; // 1
    

this的绑定

1.用Call绑定来理解
  • call的用法,将第二到最后一个参数作为函数执行时要传入的参数,把函数执行时的this指向第一个参数,执行函数。

    function say(content) { console.log("From " + this + ": Hello "+ content); } 
    say.call("Lee", "World"); //==> From Lee: Hello World 
    
  • 方便理解,可以将functionName(xxx),想成是functionName.call(window,xxxx),对于匿名函数也适用(匿名函数this指向window),但是严格模式下call的第一个参数是undefined而非window,foo() ---> foo.call(window)

    function say(word) { console.log(world); } 
    say("Hello world"); say.call(window, "Hello world"); 
    
    (function(name) { // })("aa"); //等价于 (function(name) { // }).call(window, "aa");
    
    var name = 'windowsName';
    function fn() {
      var name = 'Cherry';
      innerFunction();
      function innerFunction() {
        console.log(this.name);      // windowsName, 嵌套函数中this指向全局对象,因为它由window调用
      }
    }
    fn();
    
  • 当函数作为对象的方法被调用,可以理解为call的第一个参数指向这个对象。obj.foo() --> obj.foo.call(obj)。当对象的方法被赋给了全局变量,那么相当于window.foo.call(window),因为this永远指向调用他的那个对象。

    var obj = {}
    obj.innerobj = {
      x: 30, 
      f: function(){ 
        console.log(this.x); 
      }
    } 
    obj.innerobj.f(); // obj.innerobj.f.call(obj.innerobj) // ==> 30 
    
  • 构造函数this绑定也可以用call方法理解代替

    function person(name) { this.name = name; } 
    var foo = new person("deen");
    _newObj.constructor(name);
     //new是一种语法糖,new person等价于 
     // var bar = (function(name) { 
     //   var _newObj = { constructor : person, __proto__ : person.prototype,};
     //   _newObj.constructor.call(_newObj, name);
     //   return _newObj; 
     // })();
    
2.箭头函数绑定
  • 箭头函数的 this 始终指向函数定义时的 this,而非执行时。
  • 箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,否则,this 为 undefined。
      var name = "windowsName";
      var a = {
          name : "Cherry",
    
          func1: function () {
              console.log(this.name)     
          },
          func2: function () {
              setTimeout(  function () {
                  this.func1()
              },100);
          }
      };
      a.func2()     // this.func1 is not a function, setTimeout对象是window
      // 应该改成setTimeout( () => { this.func1() },100); // Cherry
    
3.定义变量_this保存调用函数的对象
var name = "windowsName";
var a = {
    name : "Lee",
    func1: function () {
        console.log(this.name)     
    },
    func2: function () {
        var _this = this;
        setTimeout( function() {
            _this.func1()
        },100);
    }
};
a.func2() // Lee
4.bind、apply、call
  • apply、call、bind 都是可以改变 this 的指向。

  • apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数。 fun.apply(thisArg, [argsArray]) 它的第二个参数是一个数组或者类数组对象。

  • fun.call(thisArg[, arg1[, arg2[, ...]]])。 call也是调用函数,第一个参数指定this,call接受的是参数列表。

  • bind()方法创建一个新的函数(并不会调用), 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。 绑定并调用实例:funcName.bind(a,1,2)();