ES6 箭头函数(Arrow Functions)最核心的特性之一就是它不绑定自己的 this。箭头函数中的 this 指向是在函数被创建时就确定的,它继承自外层(包裹它的)普通函数或全局作用域的 this 值。这种机制被称为 this 的词法绑定(Lexical this)。
这与传统的普通函数(使用 function 关键字定义)形成鲜明对比,普通函数的 this 是在函数被调用时动态确定的。
1. 箭头函数 this 的核心规则
- 没有自己的
this:箭头函数在执行时,不会创建自己的this上下文。 - 继承外层
this:它会沿着作用域链向上查找,使用最近的非箭头函数的this值。 - 创建时决定:
this的指向在箭头函数被定义时就已经确定,无法通过call、apply或bind方法改变。
2. 与普通函数的对比示例
场景一:作为对象方法
const person = {
name: 'Alice',
// 普通函数:this 指向调用者 (person)
greetNormal: function() {
console.log(this.name); // 'Alice'
},
// 箭头函数:this 不指向 person!
greetArrow: () => {
console.log(this.name); // undefined (在浏览器中通常是 window.name)
}
};
person.greetNormal(); // 'Alice'
person.greetArrow(); // undefined 或空字符串
- 解释:
greetArrow是一个箭头函数,它没有自己的this。它的外层是全局作用域(或模块作用域),所以this指向全局对象(浏览器中是window)。window没有name属性,因此输出undefined。
场景二:在 setTimeout 或事件回调中
这是箭头函数 this 优势最明显的场景。
function Timer() {
this.seconds = 0;
// 普通函数作为回调:this 会丢失!
setInterval(function() {
this.seconds++; // 错误!这里的 this 通常指向全局对象或 undefined (严格模式)
console.log(this.seconds); // NaN 或报错
}, 1000);
// 箭头函数作为回调:完美继承外层 this!
setInterval(() => {
this.seconds++; // 正确!this 指向 Timer 实例
console.log(this.seconds); // 每秒输出递增的数字
}, 1000);
}
const timer = new Timer();
- 解释:第一个
setInterval的回调是普通函数,当它执行时,this被设置为调用它的环境(通常是全局对象),不再是Timer实例。而箭头函数() => { ... }的this继承自外层的Timer构造函数,因此this正确地指向了Timer的实例。
场景三:在数组方法(如 map, filter)中
const numbers = [1, 2, 3];
const multiplier = {
factor: 10,
// 普通函数:需要保存 this
multiplyNormal: function() {
const self = this; // 保存 this
return numbers.map(function(num) {
return num * self.factor; // 必须用 self,不能用 this
});
},
// 箭头函数:直接使用 this
multiplyArrow: function() {
return numbers.map(num => num * this.factor); // this 指向 multiplier 对象
}
};
console.log(multiplier.multiplyNormal()); // [10, 20, 30]
console.log(multiplier.multiplyArrow()); // [10, 20, 30]
- 解释:在
multiplyNormal中,map的回调是普通函数,它有自己的this(不是multiplier),所以必须用self = this来保存外层的this。而在multiplyArrow中,箭头函数直接继承了multiplyArrow方法的this(即multiplier对象),可以直接使用this.factor。
3. 箭头函数 this 的“不可变性”
你无法通过 call、apply 或 bind 来改变箭头函数的 this 指向。
const arrowFunc = () => console.log(this);
const obj = { name: 'Bob' };
// 以下调用都无法改变 arrowFunc 内部的 this
arrowFunc.call(obj); // 仍然输出全局对象的属性
arrowFunc.apply(obj); // 同上
arrowFunc.bind(obj)(); // 同上
4. 总结
- 箭头函数没有自己的
this。 this指向外层作用域的this,在函数创建时就已确定(词法绑定)。- 不能用
call、apply、bind改变其this。 - 适用场景:
- 作为回调函数(如
setTimeout,setInterval, 事件处理器)。 - 在数组方法(
map,filter,reduce)的回调中。 - 需要确保
this指向外层函数的场景。
- 作为回调函数(如
- 不适用场景:
- 作为对象的方法(除非你明确知道
this会指向全局)。 - 需要动态
this的场景(如构造函数、需要this指向调用者的函数)。 - 需要使用
arguments对象的场景(箭头函数也没有自己的arguments)。
- 作为对象的方法(除非你明确知道
简单来说,记住:箭头函数的 this 指向它被定义时所处的环境的 this。这个特性使得它在处理回调时非常方便,避免了 this 丢失的问题。
THE END


