箭头函数
箭头函数是 ES6 引入的简洁函数写法,它没有自己的 this、arguments、prototype,适合回调和数组操作,但不能作为构造函数,也不能接收动态 this。
#frontend
#concept
#evergreen
#javascript
#ecmascript
[!info] related notes
- 所属 MOC: ECMAScript MOC, ES6 新特性 MOC
- 上位概念: JavaScript 函数总览
- 相关概念: this 关键字, call-apply-bind, arguments-object
- 面试相关: 箭头函数面试题
箭头函数
一句话定义
箭头函数是 ES6 引入的简洁函数写法,它没有自己的 this、arguments、prototype,适合回调和数组操作,但不能作为构造函数,也不能接收动态 this。
基本语法
// 普通函数
function add(a, b) {
return a + b;
}
// 箭头函数
const addArrow = (a, b) => a + b;
| 场景 | 语法 |
|---|---|
| 单参数 | x => x * 2 或 (x) => x * 2 |
| 多参数 | (a, b) => a + b |
| 无参数 | () => "hi" |
| 多行函数体 | (a, b) => { return a + b; } |
| 返回对象 | () => ({ name: "Tom" }) |
箭头函数 vs 普通函数
| 特性 | 普通 function 声明/表达式 | 箭头函数 |
|---|---|---|
| this | 运行时决定(谁调用) | 定义时从外层继承 |
| arguments | ✅ 有 | ❌ 无(用剩余参数替代) |
| constructor | ✅ 可 new | ❌ 不能 new |
| prototype | ✅ 有 | ❌ 无 |
简写方法、async 函数等并非都能 new;上表的构造能力针对普通 function。箭头函数通常没有自身 prototype 属性,即使手动添加也不会获得构造能力。
this 的核心区别
普通函数:this 由调用方式决定
const obj = {
name: "Alice",
normal() {
console.log(this.name);
}
};
obj.normal(); // Alice(this === obj)
// 提取为独立函数调用会失去 obj 接收者;call/apply/bind 也会影响普通函数的 this。
箭头函数:继承外层作用域的 this
const obj = {
name: "Alice",
arrow: () => console.log(this.name)
};
obj.arrow(); // 读取外层 this.name;ES module 顶层 this 为 undefined,会抛 TypeError
this 场景对比
场景一:定时器回调
function Timer() {
this.count = 0;
// 箭头函数:继承 Timer 的 this
setInterval(() => {
this.count++;
console.log(this.count);
}, 1000);
// 普通函数:this 会丢失
setInterval(function() {
this.count++; // 不保证是 Timer 实例;浏览器与 Node 的定时器接收者不同
}, 1000);
}
场景二:数组方法
const nums = [1, 2, 3, 4];
const doubled = nums.map(x => x * 2); // [2, 4, 6, 8]
const evens = nums.filter(x => x % 2 === 0); // [2, 4]
const total = nums.reduce((sum, x) => sum + x, 0); // 10
场景三:需要对象作为动态接收者的方法
const user = {
name: "Tom",
// 不推荐:this 不会指向 user
sayHi: () => console.log(this.name)
};
// 推荐:普通方法
const user2 = {
name: "Tom",
sayHi() { console.log(this.name); }
};
返回对象的坑
// ❌ 错误:{} 被当成函数体
const getUser = () => { name: "Tom" };
getUser(); // undefined
// ✅ 正确:用括号包起来
const getUserObject = () => ({ name: "Tom" });
getUserObject(); // { name: "Tom" }
不能用箭头函数的场景
- 需要动态接收者的对象方法 — 对象字面量不建立新的 this 作用域;class 字段中的箭头函数可捕获实例 this
- 构造函数 — 不能用 new
- 需要自身 arguments 的场景 — 用普通函数或改为 rest;箭头函数仍可读取外层 arguments
- 需要动态 this 的回调 — 某些库会改写 this
面试常考题
题 1
const obj = {
name: "Tom",
fn: () => console.log(this.name)
};
obj.fn();
答案:由外层 this 决定。ES module 顶层会抛 TypeError;经典浏览器脚本读取全局对象上的 name,而不是 obj.name。
题 2
const fn = () => ({ a: 1 });
console.log(fn());
答案:{ a: 1 }
题 3
const fn = () => { a: 1 };
console.log(fn());
答案:undefined(因为 {} 是函数体,不是对象)
实战建议
| 场景 | 推荐 |
|---|---|
| 数组 map/filter/reduce | 箭头函数 ✅ |
| 短小回调 | 箭头函数 ✅ |
| 保持外层 this | 箭头函数 ✅ |
| 对象方法 | 普通函数 ✅ |
| 构造函数 | 普通函数/class ✅ |
| 需要 arguments | 普通函数 ✅ |