ES6中的箭头函数

Arrow 函数

this 是Javascript中比较复杂的机制,ES6发明箭头函数的主要动机就是解决基于 this 编程的麻烦。

首先通过下面的代码说明一下箭头函数:

1
2
3
4
5
6
7
function foo(x,y) {
return x + y;
}

// versus

var foo = (x,y) => x + y;

箭头函数由一个参数列表(被 (..) 包围的0个或多个参数),紧跟着 => 操作符,最后是函数主题组成。

所以 (x,y) => x + y这一部分是箭头函数,然后这个函数赋值给变量 foo

如果函数体里面的语句不止一句,那么可以用 {} 将这些语句包裹起来。如果只有一条语句,那么可以省略大括号并且这条语句的结果默认作为返回值返回,即使没有 return。 下面是几个箭头函数的例子:

1
2
3
4
5
6
7
8
var f1 = () => 12;
var f2 = x => x * 2;
var f3 = (x,y) => {
var z = x * 2 + y;
y++;
x *= 3;
return (x + y + z) / 2;
};

箭头函数是匿名函数表达式,无法通过函数名来得到对箭头函数的引用。 所有的一般函数所具有的能力如,默认参数值,解构赋值,折叠参数等等,箭头函数都具有。

使用箭头函数可以让代码更加简短,易读:

1
2
3
4
5
var a = [1,2,3,4,5];

a = a.map( v => v * 2 );

console.log( a ); // [2,4,6,8,10]

对于代码比较少的函数,使用箭头函数带来的好处非常明显,但是如果代码很长,可能用正常的函数会比较清晰。

不仅仅是语法,还有 this

我们的注意力都在箭头函数可以让代码更短上,但是我们之前提到发明箭头函数的重要动机是解决 this 带来的痛点。

我们看一个例子:

1
2
3
4
5
6
7
8
9
10
var controller = {
makeRequest: function(..){
var self = this;

btn.addEventListener( "click", function(){
// ..
self.makeRequest(..);
}, false );
}
};

在上面的代码中,我们使用了 self = this 的技巧,因 this 的动态绑定,click事件发生时,调用函数的 this 并没有和 controller 绑定。

在箭头函数中,this 并不是动态绑定的,如果上面的例子使用箭头函数, this 会以我们需要的方式绑定。

1
2
3
4
5
6
7
8
var controller = {
makeRequest: function(..){
btn.addEventListener( "click", () => {
// ..
this.makeRequest(..);
}, false );
}
};

再下面的这段代码

1
2
3
4
5
6
7
8
9
10
11
var controller = {
makeRequest: (..) => {
// ..
this.helper(..);
},
helper: (..) => {
// ..
}
};

controller.makeRequest(..);

当我们执行 controller.makeRequest(..)this.helper引用失败,因为 this 这里没有指向 controller 。 this的指向是从周围的环境继承而来,所以,在上面的代码中, this 指向的是全局对象。

总结

ES6引入了箭头函数,不仅仅带来了代码的简洁,并且解决了 this 存在的一个问题。

  • 如果你的代码很短,函数里没有 this 的引用,也没有递归,你可以使用箭头函数替代之
  • 如果你的代码依赖 var self = this 或者 .bind(this) 可以使用箭头函数来替代
  • 对于其他情况,你要谨慎使用箭头函数