浅析ES6箭头函数
![](https://img.haomeiwen.com/i8757538/c2bb14e2755681a3.png)
引言
箭头函数,又称胖箭头函数,无疑是 ES6 标准中最流行的特性之一,引入编写具体函数的新方法。
以前的 ES5 语法示例
function timesTwo(params) {
return params * 2;
}
timesTwo(4); // 8
ES6 箭头函数示例
var timesTwo = params => params * 2;
timesTwo(4); // 8
函数很短! 我们可以忽略括号,直接隐式返回声明结果。
理解箭头函数和一般 ES5 函数不同表现十分重要。
变化
值得注意的一点是箭头函数的可用语法形式有很多。
我们了解下常见用法
- 无参数
如果没有参数接收,在箭头前编写括号即可
() => 42
实际上甚至并不需要括号
_ => 42
- 单参数
这种情况下括号可选
x => 42 || (x) => 42
- 多参数
必须使用括号包裹参数
(x, y) => 42
声明,和表达式对应
最基本的表现形式中,函数表达式生成值,函数声明执行操作。
箭头函数中,声明需要使用大括号包裹,只要有大括号,也需要写return
。
下面是带有if语句的箭头函数示例
var feedTheCat = (cat) => {
if (cat === 'hungry') {
return 'Feed the cat';
} else {
return 'Do not feed the cat';
}
}
块主体
如果箭头函数在块主体中,也要使用显式return
语句。
var addValues = (x, y) => {
return x + y
}
对象字面量
如果你返回对象字面量,返回值需要包裹在小括号中,强制解释器执行内部代码,返回对象字面量
x =>({ y: x })
匿名句法
记住箭头函数都是匿名的,这意味函数没有名称。
匿名会带来一些问题:
- 很难调试
当你遇到错误时,无法追踪函数名称或具体行数来。
- 没有自我引用
如果函数需要在任何点进行自我引用,如,递归,事件绑定需要解绑,都不能用箭头函数。
优点: 无需绑定
经典函数表达式中,this
关键字会根据函数被调用的上下文绑定到不同的值。
但是箭头函数需要通过语法绑定,这意味着箭头函数内部会使用包含函数代码的外部this
。
看下es5的例子:
// ES5
var obj = {
id: 42,
counter: function counter() {
setTimeout(function() {
console.log(this.id);
}.bind(this), 1000);
}
};
es5中bind(this)
会将当前上下文this
传递至函数内部,否则默认undefined
。
// ES6
var obj = {
id: 42,
counter: function counter() {
setTimeout(() => {
console.log(this.id);
}, 1000);
}
};
ES6箭头函数无法绑定至this
关键字,函数查找作用域,然后使用已经定义this
的作用域。
不能使用场景
学习箭头函数的基本知识后,我希望你会明白他们不能替代普通函数。
下面是一些你可能不能使用箭头函数的场景:
- 对象方法
当调用cat.jumps
方法时,生命计数变量不会下降。因为this
关键字没有绑定值,会继承父级作用域的this
var cat = {
lives: 9,
jumps: () => {
this.lives--;
}
}
- 带动态上下文的回调函数
如果你需要动态上下文,那就不能用箭头函数。
var button = document.getElementById('press');
button.addEventListener('click', () => {
this.classList.toggle('on');
});
如果点击按钮,会报TypeError错误。
因为this
没有指向按钮,指向了父级作用域。
- 当箭头函数降低代码可读性时
之前我们讲的多种语法形式确实值得尝试。
使用普通函数可以知道预期返回值,箭头函数可能很难从代码上直接解读出结果。
使用场景
在任何需要this
绑定至当前上下文,而不是函数本身时,箭头函数十分合适。
尽管箭头函数是匿名的,我也喜欢在map
和reduce
方法中使用,这里代码可读性更高,相对而言,优点大于缺点。
译者注
-
原文有删减,因译者水平有限,如有错误,欢迎留言指正交流