一、问题

javascript中 this 的上下文绑定是个很麻烦的问题,麻烦在不知道当前函数的 this 绑定的到底是哪个上下文。

而影响 this 的绑定方面也比较多,除了默认绑定之外,还存在硬绑定或者上下文绑定等。

二、判断this的绑定对象

1、new

在 ES5 中创建一个对象可能会使用 new 来创建:

function Person(name){
    this.name = name;
}
var person = new Person('ptbird');

在使用new的时候,已经进行了new 绑定

此时返回的对象将 this 绑定到了 新创建的对象中,因此 此时 this 绑定的是新创建的对象

下面代码也就没问题:

console.log(person.name); // ptbird

2、 call/apply/bind 硬绑定

所谓的硬绑定就是显示绑定,手动将this的上下文对象指定为绑定的对象.

    function getName() {
        console.log(this.name);
    }

    getName.bind(person)(); // ptbird;

callapply 同样也是硬绑定,和bind一样,也会将this绑定到指定的上下文(对象)中,他们的第一个参数都是需要一个对象。

3、隐式绑定

如果是上下文对象中调用了函数,则默认this绑定到上下文对象中。

function getName(){
    console.log(this.name);
}

var person = {
    name:'ptbird',
    getName:getName
}

person.getName(); // ptbird

可以看到,在上面的例子中,调用 getName 函数的实际上是 person 对象,因此 函数的 this 自然就绑定到了上下文对象中。

4、默认绑定

如果是默认情况,则this默认是绑定在全局对象或者是undefined上的,这取决于是否是严格模式

var name = 'ptbird';
function getName(){
    console.log(this.name);
}
getName(); // ptbird
'use strict';
var name = 'ptbird';
function getName(){
    console.log(this.name);
}
getName(); // 报错:无法从undefined中获取name

三、 ES6 箭头函数

ES6中箭头函数是拯救回调的 this 指向的救星。

之前写的很多的就是 var that = this; 然后在回调中使用 that 代替this。

不过 箭头函数出现之后,由于箭头函数中的this指向的定义函数的上下文环境,而非当前的执行环境,因此在回调中直接使用this也就没有任何问题了。

一个示例:

    'use strict';
    function foo() {
        setTimeout(() => {
            // 这里的this 在此法上继承自foo()
            console.log(this);
            console.log(this.name);
        }, 100);
    }
    var person = {
        name: 'ptbird'
    };
    foo.call(person);

由于严格模式,this 默认绑定在 undefined 上,因此直接指定foo函数是处错误的。

foo(); // use strict

2.png

非严格模式下,由于 foo 的上下文环境是 window,因此 this 同样会绑定在window上

foo(); // no use strict

2.png