在 JavaScript 中,this
的指向问题一直是让开发者头疼的问题。this
的指向取决于函数的调用方式,主要有以下几种绑定规则:
1. 默认绑定
当函数独立调用时,this
默认指向全局对象(在浏览器中是 window
,在 Node.js 中是 global
)。
javascript
function foo() {
console.log(this.a);
}
var a = 2;
foo(); // 2
在严格模式下,默认绑定会失效,this
会指向 undefined
:
javascript
function foo() {
'use strict';
console.log(this.a);
}
var a = 2;
foo(); // TypeError: Cannot read property 'a' of undefined
2. 隐式绑定
当函数作为对象的方法调用时,this
指向该对象。
javascript
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); // 2
需要注意的是,隐式绑定可能会丢失:
javascript
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo; // 函数别名
var a = '全局变量'; // 全局变量
bar(); // '全局变量'
3. 显式绑定
通过 call()
、apply()
或 bind()
方法,我们可以显式地指定 this
的指向。
javascript
function foo() {
console.log(this.a);
}
var obj = {
a: 2
};
foo.call(obj); // 2
foo.apply(obj); // 2
var bar = foo.bind(obj);
bar(); // 2
4. new 绑定
使用 new
关键字调用函数时,会创建一个新对象,并将 this
绑定到这个新对象上。
javascript
function foo(a) {
this.a = a;
}
var bar = new foo(2);
console.log(bar.a); // 2
绑定规则的优先级
这四种绑定规则的优先级从高到低是:
- new 绑定
- 显式绑定
- 隐式绑定
- 默认绑定
箭头函数中的 this
箭头函数不遵循上述规则,它的 this
继承自外层作用域:
javascript
function foo() {
setTimeout(() => {
console.log(this.a);
}, 100);
}
var obj = {
a: 2
};
foo.call(obj); // 2