一、this的四条绑定规则

1、默认绑定

  适用于独立函数调用,当无法应用其他规则时就适用的是默认规则。

2、隐式绑定

  需要考虑的规则时调用位置是否有上下文对象,或者说是否被某个对象拥有或者包含。

1
2
3
4
5
6
7
8
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo
}
obj.foo();

3、显式绑定

  通常使用call(…)和apply(…)进行显式绑定。

1
2
3
4
5
6
7
function foo() {
console.log(this.a);
}
var obj= {
a:2
};
foo.call(obj)

  • 硬绑定bind的实现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function foo(something) {
    console.log(this.a, something);
    return this.a + something;
    }
    // 简单的辅助绑定函数
    function bind(fn, obj) {
    return function () {
    return fn.apply(obj, arguments)
    }
    }

    var obj = {
    a: 2
    }

    var bar = bind(foo, obj);
    var b = bar(3);
    console.log(b)

4、new绑定

1
2
3
4
5
function foo(a) {
this.a=a;
}
var bar = new foo(2);
console.log(bar.a)

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

二、四条绑定规则的优先级

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

  • 判断this的方法
  1. 函数是否在new中调用,如果是的话this绑定的是新创建的对象。

    1
    var bar = new foo()
  2. 函数是否通过call、apply(显式绑定)或者硬绑定调用,如果是的话,this绑定的是指定的对象。

    1
    var bar = foo.call(obj2)
  3. 函数是否在某个上下文对象中调用(隐式调用),如果是的话,this绑定的是哪个上下文对象。

    1
    var bar = obj1.foo()

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

注:箭头函数不会使用四条标准的绑定规则,而是根据当前的词法作用域来决定this。