js——this

每个函数的this是在调用时绑定的,完全取决于函数的调用位置  

     1. 绑定规则总结        

一般情况下,按下列顺序从下至上来判断this的绑定对象(绑定的优先级从下至上递减

  • 默认:在严格模式下绑定到undefined,否则 绑定到全局对象
  • 隐式:由上下文对象调用?绑定到对应的上下文对象
  • 显示:由call或apply或bind调用?绑定到指定的对象
  • new:由new调用?绑定到新创建的对象

     2. 绑定规则说明     

  • 默认情况
    • 规则:非strict mode时,绑定到全局;strict mode时,绑定到undefined
    • 适用情况:当其它三种规则不适用时使用
var a = 2;
function f1(){
    alert(this.a);
}
function f2(){
    var a = 3;
    f1();
}
f2();//输出为2,全局定义的
View Code
  • 绑定到上下文对象(隐式绑定)
    • 函数作为对象的一个属性,则该对象就是该函数的上下文对象
function foo(){
    alert(this.a);
}
var obj2 = {
    a:42,
    foo:foo//foo作为obj2的属性
};
var obj1 = {
    a:2,
    obj2: obj2
};
obj1.obj2.foo();//输出obj2中的42,obj2是foo对象属性引用链中的最后一层
View Code
    • 隐式绑定丢失:函数作为对象的属性不代表函数属性完全属于该对象,它还是独立的。当直接引用函数时,它会用默认绑定方式(全局或undefined)
var obj = {
    a:"obj",
    foo:function(){
        alert(this.a);
    }
}
var a = "global"
var bar = obj.foo;//bar直接引用函数
bar();//输出"global"
View Code
  • 显式绑定
    • 函数不属于一个对象的属性,可利用call、apply、bind函数让this绑定到该对象上
    • foo.call(obj, param):call函数会把第一个变量obj绑定到foo函数的this上
function foo(){
    alert(this.a);
}
var obj = {//对象中没有foo属性
    a:"obj"
};
foo.call(obj);//输出obj
View Code
    • foo.apply(obj, param):apply函数的效果和使用与call相似
    • 硬绑定方法bind:newFoo = foo.bind(obj); 将foo的this绑定到obj上,并返回相应的新函数,这样就不会发生绑定丢失了
function foo(){
    alert(this.a);
}
var obj = {
    a:"obj"
};
var obj2 = {
    a:"obj2"
};
var bar = foo.bind(obj);//bind把foo的this绑定到obj对象,并返回这个函数
bar();//输出"obj"
bar.call(obj2);//仍然输出"obj",硬绑定不会被修改
View Code
    • 自定义一个bind函数:对apply、call函数进行封装,并返回一个新函数(已经绑定好对象)
function foo(){
    alert(this.a);
}
//对apply函数进行封装,让绑定在bind内部完成,并返回一个函数
//这样,就不能通过封装后的函数修改绑定
function bind(fun, obj){
    return function(){  
        //apply函数返回值为undefind
        fun.apply(obj, arguments);
    };
}
var obj = {
    a:"obj"
}
var bar = bind(foo, obj);
bar();//输出"obj"
bar.apply(window);//仍然输出"obj"
View Code
  • new绑定
    • new foo(); 用new调用一个函数时,它会把foo的this绑定到创建的新对象
function foo(a){
    this.a = a;
}
var bar = new foo(2);
alert(bar.a);//输出 2
View Code

     3. 特殊情况     

  • null和undefined传给call、apply、bind时,使用默认绑定规则。在做柯里化时可以用到
  • 为了不让这种情况下的this绑定到全局(从而影响全局的值),可以自定义一个空对象,并将它作为这几个函数的第一个参数
  • 软绑定:如果this绑定到全局或undefined,那就让它绑定到给定的对象,否则不变
  • 箭头函数:箭头函数的this绑定对象与其外层作用域是一致的

参考:

1. 《你不知道的javascript》上卷 

原文地址:https://www.cnblogs.com/coolqiyu/p/7135952.html