this的绑定梳理

364 阅读3分钟

1 默认绑定

function foo(){
    var a = 1 ;
    console.log(this.a);    // 10
}
var a = 10;
foo();

默认绑定到哪呢,一般是window上,严格模式下 是undefined。调用foo,this.a打印的值为10

2 隐性绑定

function foo(){
    console.log(this.a);
}
var obj = {
    a : 10,
    foo : foo
}
foo();                // ?

obj.foo(); 

foo()的这个写法熟悉吗,就是我们刚刚写的默认绑定,等价于打印window.a,故输出undefined ,
下面obj.foo()这种大家应该经常写,这其实就是我们马上要讨论的 隐性绑定

函数foo执行的时候有了上下文对象,即 obj。这种情况下,函数里的this默认绑定为上下文对象,等价于打印obj.a,故输出10

答案:undefined,10

3 显性绑定

3 .1 隐性绑定的限制

var obj = { foo : foo },如果上下文不包含我们的函数用隐性绑定明显是要出错的,不可能每个对象都要加这个函数 ,那样的话扩展,维护性太差了,我们接下来聊的就是直接 给函数强制性绑定this

3 .2 call apply bind

这里我们就要用到 js 给我们提供的函数 call 和 apply,它们的作用都是改变函数的this指向第一个参数都是 设置this对象

  1. call从第二个参数开始所有的参数都是 原函数的参数。
  2. apply只接受两个参数,且第二个参数必须是数组,这个数组代表原函数的参数列表。
function foo(a,b){
    console.log(a+b);
}
foo.call(null,'海洋','饼干');        // 海洋饼干  这里this指向不重要就写null了
foo.apply(null, ['海洋','饼干'] );     // 海洋饼干
除了 call,apply函数以外,还有一个改变this的函数 bind ,它和call,apply都不同。

bind只有一个函数,且不会立刻执行,只是将一个值绑定到函数的this上,并将绑定好的函数返回

function foo(){
    console.log(this.a);
}
var obj = { a : 10 };

foo = foo.bind(obj);
foo(); 

js中的只要用new修饰的 函数就是'构造函数',准确来说是 函数的构造调用,因为在js中并不存在所谓的'构造函数'。

那么用new 做到函数的构造调用后,js帮我们做了什么工作呢:

  1. 创建一个新对象。
  2. 把这个新对象的__proto__属性指向 原函数的prototype属性。(即继承原函数的原型)
  3. 将这个新对象绑定到 此函数的this上
  4. 返回新对象,如果这个函数没有返回其他对象

4 .1 new 绑定

function foo(){
    this.a = 10;
    console.log(this);
}
foo();                    // window对象
console.log(window.a);    // 10   默认绑定

var obj = new foo();      // foo{ a : 10 }  创建的新对象的默认名为函数名
                          // 然后等价于 foo { a : 10 };  var obj = foo;
console.log(obj.a);       // 10    new绑定

使用new调用函数后,函数会以自己的名字 命名 和 创建一个新的对象,并返回。

4.2this绑定优先级

new 绑定 > 显示绑定 > 隐式绑定 > 默认绑定

总结

1如果函数被new 修饰

this绑定的是新创建的对象,例:var bar = new foo(); 函数 foo 中的 this 就是一个叫foo的新创建的对象 , 然后将这个对象赋给bar , 这样的绑定方式叫 new绑定 

2.如果函数是使用call,apply,bind来调用的

this绑定的是 call,apply,bind 的第一个参数.例: foo.call(obj); , foo 中的 this 就是 obj , 这样的绑定方式叫 显性绑定 .

3.如果函数是在某个 上下文对象 下被调用

this绑定的是那个上下文对象,例 : var obj = { foo : foo }; obj.foo(); foo 中的 this 就是 obj . 这样的绑定方式叫 隐性绑定

4.如果都不是,即使用默认绑定

   例:function foo(){...} foo() ,foo 中的 this 就是 window.(严格模式下默认绑定到undefined).
   这样的绑定方式叫 默认绑定 .

参考文献:https://segmentfault.com/a/1190000011194676#articleHeader13