ES6 箭头函数
箭头函数是 ES6 里出现频率最高的语法之一,写法从 function 变成了 =>。
很多人以为它只是”函数简写”,但它还有一个根本性变化:this 的指向。
这篇讲清楚两件事——怎么写、以及 this 到底有什么不同。
箭头函数怎么写
先看最直观的对比:
// ES5:function 关键字
function add(a, b) {
return a + b;
}
// ES6:箭头函数
const add = (a, b) => a + b;
三种写法规则
箭头函数有两种”形态”——表达式形态和声明形态,先看最基本的:
// ① 完整写法:有参数、函数体多行、需要 return
const add = (a, b) => {
return a + b;
};
// ② 单表达式写法:函数体只有一行,可以不加 {} 和 return(自动返回)
const add2 = (a, b) => a + b;
// ③ 只有一个参数时,连括号都可以省
const double = x => x * 2;
三个规律:
| 情况 | 写法 |
|---|---|
| 只有一个参数 | 括号可省略:x => ... |
| 没有参数 | 括号不能省:() => ... |
| 函数体只有一行 | 省略 {} 和 return,自动返回该值 |
自动返回那个功能很常用。但你保留
{}时,就必须手动写return,否则返回undefined。
箭头函数不是”到处都能用”
箭头函数有两条硬性规则:
- 不能做构造函数:
new是”创建对象实例”的关键字(后面 class 一章也会用到),箭头函数不能配合new使用(会报错)。 - 没有
arguments对象:arguments是普通函数自带的”当前实参集合”对象。箭头函数内部拿不到它(需要的话可以用 rest 参数代替,后面函数扩展一章讲)。
这两条先记住结论即可,等用到时自然就理解了。
关键区别:this 指向
这是箭头函数最难、也最重要的内容。
普通函数的 this:谁调用,指向谁
普通函数的 this 是调用时确定的——谁调用它,this 就是谁:
// 示例
function getName() {
console.log(this); // 取决于调用方式
}
getName(); // 浏览器里 this 是 window
const obj = { getName };
obj.getName(); // 由 obj 调用,this 就是 obj
箭头函数的 this:定义时确定,不随调用变化
箭头函数没有自己的 this,它用的是定义时所处外层作用域的 this,之后不管怎么调用都不变。这是它和普通函数最大的区别。
看一个新手最容易踩的坑——定时器里丢失 this:
// ES5 写法:this 会丢(问题代码)
const user = {
name: '小明',
show() {
setTimeout(function () {
console.log(this.name); // 报错/undefined
}, 100);
}
};
上面 setTimeout 里的普通函数,它调用时由浏览器执行,this 变成了全局对象,访问不到 user.name。
换成箭头函数,问题消失:
// ES6 写法:箭头函数,this 指向外层 user
const user = {
name: '小明',
show() {
setTimeout(() => {
console.log(this.name); // 小明
}, 100);
}
};
因为箭头函数用的 this 是定义时外层作用域的 this——也就是 show 方法里的 this,即 user。定时器触发时,this 依然是 user。
一句话记忆:
普通函数:this 看”谁调用”;箭头函数:this 看”在哪定义”。
什么时候用箭头函数
| 场景 | 选择 |
|---|---|
写数组方法回调(map、filter) |
箭头函数,简洁 |
定时器、事件回调里需要访问外层 this |
箭头函数 |
定义对象的方法(需要 this 指向对象) |
普通方法 |
需要动态 this(如事件解绑、构造函数) |
普通函数 |