this的5种绑定情况

前面的话

关于this指向问题,大家都不陌生,最近做题一些面试题,正好碰到,将其绑定的方式总结一下。

默认绑定
  • 独立函数调用: 在普通函数中调用,this指向的全局对象window
  • 严格模式下: 比较特殊,运行在严格模式不能将全局对象绑定到window,而是绑定到undefined。只有函数运行在非严格模式下,才会绑定到window。而函数在严格模式下调用,则不会影响默认绑定。
// 默认绑定
    function foo() {
        console.log(this.a);
    }
    var  a = 2;
    foo();


// 运行在严格模式下:
 function foo() {
        "use strict";
        console.log(this.a); 
 }
 var  a = 2;
 foo();// Uncaught TypeError: Cannot read property 'a' of undefined


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

(function(){
        "use strict";
        foo();
    })() 
隐式绑定

当函数引用有上下文对象时,隐式绑定规则会把函数的this绑定到这个上下文对象。

function foo() {
        console.log(this.a);
    }
    obj = {
        a : 1,
        foo: foo
    }
    // 这里this绑定给了obj
    obj.foo(); // 1

这里foo被obj添加到其属性上,最终被obj包含。

注意,只有对象属性引用链的最后一层才会影响调用点:

function foo() {
    console.log( this.a );
}

var obj2 = {
    a: 42,
    foo: foo
};

var obj1 = {
    a: 2,
    obj2: obj2
};

obj1.obj2.foo(); // 42

这里obj2这个对象被添加到obj1对象上作为属性,obj1.obj2.foo()其最终调用者是obj2,this会指向obj2,所返回42.

隐式丢失

被隐式绑定的函数特定情况下回丢失绑定对象,应用为默认绑定,把this绑定到全局对象或者undefined上。

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

    var bar = obj.foo;
    var a = 'xiaoqi';
    bar(); // xiaoqi

这里var bar = obj.foo;相当于var bar = function foo() {this.a};以默认绑定的情况一样。

function foo() {
        console.log(this.a);
    }
    function doFoo(fn) {
            fn(); 
    }
    var obj = {
        a:2 ,
        foo:foo
    };
    var  a = 'xiaoqi';
    doFoo(obj.foo); // xiaoqi

这里obj.foo只是foo的一个引用,并没有真正的调用,所以最终this绑定的函数全局对象。

显式绑定

通过call()或者apply()方法。第一个参数是对象,在调用函数时将这个对象绑定到this。因为直接指定了this的绑定对象,称之为显示绑定。

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

    foo.call(obj);//2

这里调用foo时强制把foo的this绑定到obj。

硬性绑定

未解决显示绑定无法解决丢失绑定的问题。

function foo() {
        console.log( this.a );
    }

    var obj = {
        a: 2
    };

    var bar = function() {
        foo.call( obj );
    };

    bar(); // 2
    setTimeout( bar, 100 ); // 2

    // `bar`将`foo`的`this`硬绑定到`obj`
    // 所以它不可以被覆盖
    bar.call( window ); // 2

创建一个函数bar(),在其内部手动调用foo.call(obj),由此强调this绑定到obj.无论以后怎么调用函数bar,因为它总是手动使用obj调用foo。this都无法被改变,所有叫做硬绑定。

ES5内置的Function.prototype.bind,bind会返回一个硬绑定的新函数

function foo(something) {
    console.log( this.a, something );
    return this.a + something;
}

var obj = {
    a: 2
};

var bar = foo.bind( obj );

var b = bar( 3 ); // 2 3
console.log( b ); // 5

这里的bind会改变this的指向,同时返回一个新函数,这一点与call和apply不同。

new绑定

这个就比较简单了,构造函数中this指向实例化对象。

function foo(a) {
    this.a = a;
}

var bar = new foo(2); // bar和foo(..)调用中的this进行绑定
console.log( bar.a ); // 2
箭头函数绑定

记住:箭头函数中的this始终指向其父级作用域中的this。换句话说,箭头函数会捕获其所在的上下文的this值,作为自己的this值。在箭头函数中调用 this 时,仅仅是简单的沿着作用域链向上寻找,找到最近的一个 this 拿来使用,它与调用时的上下文无关。

var obj = {
a: 10,
b: () => {
    console.log(this.a);// undefined
    console.log(this);// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ,        parent: Window, …}
},
c: function() {
    console.log(this.a);// 10
    console.log(this);// {a: 10, b: ƒ, c: ƒ, d: ƒ}
},
d: function () {
    return () => {
        console.log(this.a);// 10
    }
}
}
obj.b();
obj.c();
obj.d()() 

上例中: obj.b()中的this会继承父级上下文中的this值,也就是window。
obj.c()的this指向即为调用者obj,obj.d()()的this也是继承父级上下文中的this, 即d的this指向为obj.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值