YDNJS(上卷):this 的绑定对象
函数中的
this
是在调用时被绑定的,this
指向谁完全取决于函数的调用位置。
确定 this
的绑定对象的方式有 4 种。
默认绑定
默认绑定就是将函数中的 this
绑定给了全局对象 window
。这往往适用于我们调用函数时,不带有任何修饰的情况。
function foo() {
console.log(this.a);
}
var a = 2;
foo(); // 2
我们调用函数 foo
的方式是直接调用,所以函数执行时,函数中的 this
是指向全局对象 window
, 取 window
对象的 a
属性,就是取全局变量 a
,所以打印出的结果是 2。
隐式绑定
隐式绑定就是将函数作为对象属性调用。这时函数内部的 this
指向对象本身。
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); // 2
上面的代码中,我们以 obj
对象的属性形式,调用了 foo
函数,这时函数中的 this
就是对象 obj
,this.a
就是 obj.a
,自然就是 2 了。
还有,对于隐式绑定,函数的调用位置是 对象属性引用链中的最后一层。
function foo() {
console.log(this.a);
}
var obj2 = {
a: 42,
foo: foo
};
var obj1 = {
a: 2,
obj2: obj2
};
obj1.obj2.foo(); // 42
对象属性引用链中的最后一层是 obj2
,foo
是它的一个属性,所以 foo
函数执行时,内部 this
指向 obj2
对象,所以打印结果是 42。
显式绑定
显示绑定就是使用函数的 call()
或者 apply()
方法,为执行的函数显式指定上下文执行对象,也就是显式指定执行函数内部的 this
指向的对象。
函数的 call()
或者 apply()
方法接收的第一个参数是一个对象,在调用函数时会将这个对象绑定给 this
。就是说是直接给 this
指定绑定的对象,因此称为显式绑定。
function foo() {
console.log(this.a);
}
var obj = {
a: 2
};
foo.call(obj); // 2
new 绑定
在传统的面向类的语言中,「构造函数」是类中的一个特殊方法,在使用 new
初始化类实例时会被自动调用。
需要清楚得是:JavaScript 中 new
的机制与面向类的语言中的 new
完全不同。
在 JavaScript 中,根本就不存在「构造函数」,只有对函数的「构造调用」。JavaScript 中的所有函数都可以用 new
调用,这种函数调用称为对函数的「构造调用」。
使用 new
来调用函数,或者说在对函数进行「构造调用」时,会自动执行下列步骤:
- 创建一个全新的对象。
- 新对象执行
[[Prototype]]
连接。 - 被调用函数中的
this
绑定到这个新对象。 - 如果函数没有返回其他对象,则返回这个新对象。
下面是一个例子:
function foo() {
this.a = a;
}
var bar = new foo(2);
bar.a; // 2
我们使用 new
来调用 foo()
时,会创建一个全新的对象,然后 foo
函数内部的 this
就会绑定到这个新对象上。
优先级
new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定