一:this 绑定规则

114 阅读2分钟

1:默认绑定

//非严格模式下
function foo(){
    console.log(this.a)
}
var a = 2;
foo();//a

//严格模式下
function foo(){
    "use strict"
    console.log(this.a)
}
var a = 2;
foo();//TypeError:this is undefined

//这种 特殊情况也能绑定到全局作对象 最好不要混用strict模式和非strict模式function foo(){

    console.log(this.a)
}
var a = 2;
(function(){
 "use strict"
foo();//2
})();

2:隐式绑定

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

obj.foo();//2

function foo(){
    console.log(this.a)
}
var obj1 ={
    a:1,
    obj2:obj2
};
var obj2 ={
    a:2,
    foo:foo
};obj1.obj2.foo();//2
//对象属性引用链中只有上一层或者说最后一层在调用位置中起作用。

//隐式丢失
function foo(){
    console.log(this.a)
}
var obj ={
    a:2,
    foo:foo
};
var bar = obj.foo;

var a = "oops,global";
bar() ;//"oops,global";//这是因为bar 实际上引用的是foo函数本身,应用的是默认绑定。

//隐式丢失 ,回调函数模式
function foo(){
    console.log(this.a)
}
function doFoo(fn){
    //fn 其实引用的是foo
    fn(); // 调用位置
var obj ={
    a:2,
    foo:foo
};

var a = "oops,global";
doFoo(obj.foo) ;//"oops,global";

3:显示绑定

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

obj.call(obj);//2
// 通过foo.call() 我们可以在调用foo时 强制把它的this 绑定到obj上

4:new 绑定

使用new来调用foo()时,我们会构造一个新对象并把它绑定到foo()调用中的this 上;new 是最后一种可以影响函数调用时this绑定行为的方法,我们称之为new绑定。

function foo(a){
    this.a = a ;
}
var bar = new foo(2);
console.log(bar.a); // 2

绑定的优先级

毫无疑问,默认绑定的优先级是四条规则中最低的。

隐式绑定和显示绑定哪个优先级更高

function foo(){
    console.log(this.a)
}
var obj1 ={
    a:1,
    foo:foo
};
var obj2 ={
    a:2,
    foo:foo
};
obj1.foo();//1
obj2.foo();//2

obj1.foo.call(obj2);//2
obj2.foo.call(obj1);//1
//很明显 显示绑定的优先级更高

new  绑定和隐式绑定优先级谁高谁低

function foo(something){
    this.a = something;
}
var obj1 ={
    foo:foo
};
var obj2 ={};
obj1.foo(2);
console.log( obj1.a) ;//2

obj1.foo.call(obj2,3);
console.log( obj2.a) ;//3

var bar = new obj1.foo(4)
console.log(obj1.a);//2
console.log(bar.a);//4
// 可以看到 new 绑定比隐式绑定优先级高

总结

  现在我们可以根据优先级来判断函数在某个调用位置应用的是哪条规则,可以按照瞎买的顺序来进行判断

   1:函数是否在new中 调用(new 绑定)?如果是的话 this绑定的是新创建的对象。

       var bar  = new foo();

   2:函数是否通过call ,apply(显示绑定)或者硬绑定来调用,是的话 this绑定的是指定的对象

     var bar = foo.call(obj)

  3:函数是否在某个上下对象中调用(隐式绑定)?如果是的话,this绑定的是哪个上下文对象。

var bar = obj.foo();

  4:如果以上都不是的话,使用默认绑定,如果在严格模式下,就绑定到undefined否则绑定到全局对象。

var bar = foo();

凡事都有例外

function foo(a){
   console.log(this.a); 
}
var a = 2;
foo.call(null) //2
// 如果把null或者undefined 座位this绑定的对象传入call,apply 或者bind 这些值在调用时会被忽略,实际应用的是默认绑定规则