在 JavaScript 中使用箭头函数
返回基本类型
许多现代编程语言都支持箭头函数的语法,例如 C#、Swift,而 ES6 也将箭头函数加入到 JavaScript 的语法中。我们在原生的 JS 中已经拥有了匿名函数,但一个更为简洁的表达式不仅方便书写,且能更为直观的表达语义。
当仅有一个参数且返回结果是一个表达式时,语法如下所示:
[1,2,3].map( num => num*2 )
// <- [2,4,6]
如果我们用 ES5 ,他会是这样的:
[1,2,3].map(function(num){
return num*2;
});
当我们不需要参数,或者要传入两个或者更多参数,我们必须用()来包含这些参数(即使没有):
[1,2,3,4].map((num,index) => num*2+index)
//<- [2,5,8,11]
当然,更多情况下我们不仅仅返回单一的表达式,还会写一些逻辑语句。这些语句,我们写在 { } 中,如下:
[1,2,3,4].map(num => {
var multiplier = 2+num;
return multiplier*num;
})
//<-[3,8,15,24]
同样适用于多个参数的情形:
[1,2,3,4].map((num,index) => {
var multiplier = 2+index;
return multiplier*num;
})
//<-[2,6,12,20]
返回对象
当我们使用箭头函数返回一个对象时,我们需要使用()包含这个对象,不然就会出现语法错误。
例1中,编译器将 number: n 解析为函数中的语句(number 解析为标签,n 解析为表达式,而这其实是不合法的),但并没有 return 语句,所以 map 的返回值为 undefined。
例2中,something: ' else ' 对编译器来说并无任何含义,所以抛出了语法错误。
[1, 2, 3].map(n => { number: n })
// [undefined, undefined, undefined]
[1, 2, 3].map(n => { number: n, something: 'else' })
// <- SyntaxError
[1, 2, 3].map(n => ({ number: n }))
// <- [{ number: 1 }, { number: 2 }, { number: 3 }]
[1, 2, 3].map(n => ({ number: n, something: 'else' }))
/* <- [
{ number: 1, something: 'else' },
{ number: 2, something: 'else' },
{ number: 3, something: 'else' }]
*/
函数作用范围
箭头函数的作用范围与其作用域绑定,也就是说当你在函数内部深层嵌套函数时,不用通过 var self = this 或者 .bind(this) 来维持上下文
function Timer () {
this.seconds = 0
setInterval(() => this.seconds++, 1000)
}
var timer = new Timer()
setTimeout(() => console.log(timer.seconds), 3100)
// <- 3
值得注意的是,ES6的箭头函数对 this 进行绑定,意味着 .call 和 .apply 不再能改变函数的上下文。
结论
当你需要一个匿名函数来返回某些表达式时,箭头函数是简洁的,并在某种程度上让你的代码更加的精简。
但并不是任何情况下,都适合使用箭头函数。当参数过多,函数体逻辑较复杂时,命名函数使得你的程序更加可读。
箭头函数的优越性体现在函数式编程的情形,.map, .filter, 或者 .reduce。同样,在异步流程控制中,箭头函数消除了大量 callback 函数带来的阅读障碍,会是一个优秀的选择。