Google 搜索出来的两个不错的链接:
我是先阅读的 You-Dont-Know-JS: this & Object Prototypes 。再回过头看上面的那两篇文章,我觉得他们讲解的太复杂了,而 《You-Dont-Know-JS》 就归纳的非常好。
以下是总结笔记:
JS 中的 this
总是指向一个对象 (Object),这个对象是基于函数运行时 动态绑定 的。要判断 this
的绑定对象,首先找到这个函数的直接调用位置,然后应用下面四条规则来判断:
- (new 绑定)由
new
调用?绑定到新创建的对象。 - (强制绑定)由
call
或者 apply
(或者 bind
)调用?绑定到指定的对象。 - (隐式绑定)由上下文对象调用?绑定到那个上下文对象。
- (默认绑定)在严格模式下绑定到
undefined
,否则绑定到全局对象。
例外,ES6 中的箭头函数会继承外层函数调用的 this
绑定。(和 ES6 之前代码中的 self = this
机制一样)
默认绑定
1
2
3
4
5
6
7
8
| function foo() {
console.log( this.a );
}
var a = 2;
foo(); // 输出 2
// 绑定到全局对象 a, 如果是严格模式,绑定到 undefined
|
隐式绑定
1
2
3
4
5
6
7
8
9
10
11
| function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); // 输出 2
// 由对象 obj 调用,绑定到 obj
|
注意:隐式绑定的丢失问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo; // 注意这个引用!
var a = "oops, global"; // 全局对象 a
bar(); // 输出: "oops, global" 绑定丢失!
setTimeout( obj.foo, 100 ); // 输出: "oops, global" 绑定丢失!
|
强制绑定: apply, call, bind
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| function foo() {
console.log( this.a );
}
var obj = {
a: 2
};
var bar = function() {
foo.call( obj ); // 将 foo 的 this 强制绑定到对象 obj
};
bar(); // 输出:2
setTimeout( bar, 100 ); // 输出: 2
// 强制绑定的对象无法被覆盖
bar.call( window ); // 2
|
new 绑定
1
2
3
4
5
6
| function foo(a) {
this.a = a;
}
var bar = new foo( 2 ); // 使用 new 绑定到对象 bar
console.log( bar.a ); // 输出 2
|
文章作者
贤民
上次更新
2018-01-14
许可协议
原创文章,如需转载请注明文章作者和出处。谢谢!