🚀 深度解析:箭头函数 vs 普通函数中的区别
在 JavaScript 中,this
的指向是一个经典难点,也是面试高频考点。尤其是箭头函数的出现,让很多开发者在日常开发中“踩坑”不断。
本文将系统讲解箭头函数与普通函数在 this
指向上的差异、整体区别、适用场景和典型陷阱,帮助你彻底搞懂这部分内容。
🔍 一、什么是 this?
this
是 JavaScript 中的一个上下文关键字,它的值取决于函数被调用时的方式。
常见场景:
-
全局上下文中
-
对象方法中
-
构造函数中
-
DOM 事件中
-
定时器/回调函数中
🎯 二、箭头函数 vs 普通函数全方位对比
1. 语法定义
function normalFn() {
console.log('普通函数 this:', this);
}
const arrowFn = () => {
console.log('箭头函数 this:', this);
}
2. this 绑定方式
-
普通函数:
this
的绑定取决于调用方式,默认指向全局对象(非严格模式),严格模式下为undefined
-
箭头函数:没有自己的
this
,它继承自定义时所在的词法作用域
3. 能否作为构造函数
-
普通函数可以通过
new
来创建实例 -
箭头函数不能使用
new
,否则会抛出错误
4. 可否使用 bind、call、apply 改变 this
-
普通函数支持这些方法,
this
会被改变 -
箭头函数不支持,
this
无法被重新绑定
5. 是否拥有 arguments 对象
-
普通函数内部有
arguments
-
箭头函数没有
arguments
,可用 rest 参数替代
6. prototype 原型属性
-
普通函数有
prototype
-
箭头函数没有
prototype
🧪 三、this 指向的对比示例
示例 1:对象方法中的 this
const obj = {
name: 'ChatGPT',
normalFn() {
console.log('普通函数:', this.name);
},
arrowFn: () => {
console.log('箭头函数:', this.name);
}
};
obj.normalFn(); // ChatGPT
obj.arrowFn(); // undefined(this 不是 obj)
示例 2:setTimeout 中 this
const obj = {
count: 10,
start: function () {
setTimeout(function () {
console.log('普通函数 this.count:', this.count);
}, 1000);
setTimeout(() => {
console.log('箭头函数 this.count:', this.count);
}, 1000);
}
};
obj.start();
// 普通函数 this.count: undefined(指向 window/node)
// 箭头函数 this.count: 10(继承自 start 方法中的 this)
示例 3:构造函数行为
function Person(name) {
this.name = name;
}
const p = new Person('Tom'); // ✅ 正常工作
const ArrowPerson = (name) => {
this.name = name;
};
const ap = new ArrowPerson('Tom'); // ❌ TypeError: ArrowPerson is not a constructor
🧠 四、场景总结:何时该用箭头函数?
场景 | 推荐函数类型 | 原因 |
---|---|---|
类方法 / 对象方法 | 普通函数 | this 应该指向调用者对象 |
回调函数(如 map, forEach) | 箭头函数 | 继承外部 this,代码更简洁 |
setTimeout/setInterval 中 | 箭头函数 | 避免 this 丢失 |
React 组件中方法 | 箭头函数(或绑定) | 避免绑定麻烦 |
Vue 组件中的 methods | 普通函数 | 保持 this 指向组件实例 |
❗️五、注意事项和坑
-
不要在对象方法中使用箭头函数,否则
this
不是对象 -
箭头函数无法作为构造函数,即不能用
new
调用 -
箭头函数没有
arguments
、super
、new.target
-
不要在需要动态上下文的地方使用箭头函数,如事件处理、类方法中
✅ 六、小结对比表
对比维度 | 普通函数 | 箭头函数 |
---|---|---|
this 绑定方式 | 动态,调用时确定 | 静态,定义时确定 |
能否用 new 构造 | ✅ | ❌ |
是否可 bind / call | ✅ | ❌(无效) |
是否有 arguments | ✅ | ❌ |
是否有 prototype | ✅ | ❌ |
适合用于构造函数 | ✅ | ❌ |
👉 总结一句话:箭头函数更适合轻量表达式、无上下文依赖的函数,而普通函数更适合上下文绑定明确、依赖 this 的场景。
🧑💻 希望本文能帮助你真正搞懂箭头函数与普通函数的区别,欢迎点赞收藏+评论交流你踩过的 this 坑!