在 JavaScript 中,箭头函数(Arrow Function) 是 ES6 引入的一种新函数语法,它与普通函数在 this 的绑定机制上有本质区别。
✅ 一句话总结
箭头函数没有自己的
this,它的this是词法作用域继承而来的,也就是说,它会捕获定义时所在上下文的this值,并且这个this永远不会改变。
✅ 一、箭头函数的 this 特点
| 特点 | 说明 |
|---|---|
没有自己的 this | 箭头函数不会创建自己的 this 上下文 |
继承外层作用域的 this | 它的 this 是从定义时的外层函数或全局作用域继承来的 |
this 固定不变 | 无论怎么调用,this 都不会改变 |
| 不能作为构造函数 | 不可以使用 new 调用(因为没有自己的 this) |
✅ 二、示例解析
示例 1:普通函数 vs 箭头函数的 this
const obj = {
name: 'Tom',
sayNameNormal: function() {
console.log(this.name);
},
sayNameArrow: () => {
console.log(this.name);
}
};
obj.sayNameNormal(); // 'Tom'(this 指向 obj)
obj.sayNameArrow(); // undefined(this 指向全局对象 window/global)
📌 解释:
sayNameNormal是普通函数,this指向调用者obj;sayNameArrow是箭头函数,其this继承自外层作用域(全局作用域),此时this.name是undefined;
示例 2:嵌套函数中的 this
const obj = {
name: 'Tom',
getArrow() {
return () => {
console.log(this === obj); // true
};
}
};
const arrowFn = obj.getArrow();
arrowFn(); // true
📌 解释:
getArrow()是一个普通函数,它的this指向obj;- 箭头函数内部的
this继承自getArrow()的this,也就是obj; - 所以即使
arrowFn被单独调用,它的this依然指向obj;
✅ 三、Babel 转译帮助理解箭头函数的 this
Babel 在将 ES6 箭头函数转译为 ES5 代码时,会使用一个技巧:用变量保存外层 this。
ES6 原始代码:
const obj = {
getArrow() {
return () => {
console.log(this === obj);
};
}
}
Babel 转译后的 ES5 代码:
var obj = {
getArrow: function getArrow() {
var _this = this;
return function () {
console.log(_this === obj);
};
}
};
📌 总结:
箭头函数本质上是通过“捕获”外层
this的方式实现的,这与 Babel 的_this = this技术是一致的。
✅ 四、常见面试题:setTimeout 中的 this
const obj = {
name: 'Tom',
sayHello: function() {
setTimeout(function() {
console.log(this.name); // undefined
}, 1000);
},
sayHelloArrow: function() {
setTimeout(() => {
console.log(this.name); // 'Tom'
}, 1000);
}
};
obj.sayHello(); // 普通函数,this 指向 window
obj.sayHelloArrow(); // 箭头函数,this 继承外层 sayHello 的 this
📌 结论:
在回调函数中使用箭头函数是解决
this丢失问题的常见做法。
✅ 五、一句话总结
箭头函数的
this是在定义时就确定的,继承自外层作用域的this,并且永远不会改变。它是词法作用域绑定的,不是运行时绑定的。因此,在需要稳定this的场景(如回调函数、事件处理)中,箭头函数是非常理想的选择。
💡 进阶建议
- 在 Vue / React 中,组件方法推荐使用箭头函数自动绑定
this; - 使用 TypeScript 可以更好地理解函数类型和
this的指向; - 使用 ESLint 规则防止误将箭头函数当作构造函数使用;
- 在类中使用类字段箭头函数(Class Field Arrow Function)可自动绑定
this;