探秘ES6】:箭头函数

更新时间:2015-07-10 09:51:33点击次数:2213次

ES6作为新一代JavaScript标准,已正式与广大前端开发者见面。为了让大家对ES6的诸多新特性有更深入的了解,Mozilla Web开发者博客推出了《ES6 In Depth》系列文章。CSDN已获授权,将持续对该系列进行翻译,组织成【探秘ES6】系列专栏,供大家学习借鉴。本文为该系列的第七篇。 

本文接下来讲述的是有关ES6箭头函数(Arrow functions)的使用。

热身

箭头符号在JS中一直扮演着重要的角色。在JS教程里,一开始都会介绍如何使用箭头括号来加注释。例如:


[js] view plaincopy

  1. <script language="javascript">  

  2. <!--  

  3.   document.bgColor = "brown";  // red  

  4. // -->  

  5. </script>  


旧版浏览器接收的是两个不支持的标签和一句注释,只有新版浏览器才会识别这是JS代码。

为了处理这种奇怪的表达方式,浏览器的JS引擎会把<!—识别为一行注释的开始位置。这种处理机制一直沿用至今,现在于Node中也适用。除此之外,-->还可以作为递增/减的操作符,例如while(n-->0) //n递减至0。

我们先回顾下箭头符号的一般用法:


  • <!-- 单行注释

  • -->  递增/减的操作符

  • <=   小于等于

  • =>   ?


=>是ES6中新的用法,也就是本节要讲述的内容。

随处可见的函数式表达

在JS中很有意思的地方是当我们需要调用函数时,只需在运行代码中的恰当位置添加就可以了。例如要对按钮的点击做出响应,可以这样写:


[js] view plaincopy

  1. $("#confetti-btn").click(function (event) {  

  2.   playTrumpet();  

  3.   fireConfettiCannon();  

  4. });  


在JS开始盛行前,这样的代码是令人奇怪的,因为很多语言当时都没有类似的写法。除了1958年List语言的lambda(匿名)函数有函数表达式功能,C++、Python、C#等语言长时间里都是没有的。到了现在,lambda已经随处可见了,这多亏了JS的功劳。例如,


[js] view plaincopy

  1. // A very simple function in six languages.  

  2. function (a) { return a > 0; } // JS  

  3. [](int a) { return a > 0; }  // C++  

  4. (lambda (a) (> a 0))  ;; Lisp  

  5. lambda a: a > 0  # Python  

  6. a => a > 0  // C#  

  7. a -> a > 0  // Java  


新的箭头语法

ES6引入了新的箭头函数编写方式。


[js] view plaincopy

  1. // ES5  

  2. var selected = allJobs.filter(function (job) {  

  3.   return job.isSelected();  

  4. });  

  5.   

  6. // ES6  

  7. var selected = allJobs.filter(job => job.isSelected());  


当需要编写一个简单的单一参数函数时,可以采用箭头函数来书写,标识名=>表达式。这样就可以省却function和return的输入,还有括号,分号等。

当需要编写一个含有多个参数的函数时,只要把相关参数用括号包起来就好了。


[js] view plaincopy

  1. // ES5  

  2. var total = values.reduce(function (a, b) {  

  3.   return a + b;  

  4. }, 0);  

  5.   

  6. // ES6  

  7. var total = values.reduce((a, b) => a + b, 0);  


我认为这是简洁的书写格式。

箭头函数的功用与Underscore.js和immutable等库的功能类似,immutable的示例文档中全部都是使用ES6来编写的,因此使用了大量的箭头函数。

除了函数样式编写,箭头函数还可以包含区块语句而不仅仅是单一表达式。例如:


[js] view plaincopy

  1. / ES5  

  2. $("#confetti-btn").click(function (event) {  

  3.   playTrumpet();  

  4.   fireConfettiCannon();  

  5. });  


ES6的写法为:


[js] view plaincopy

  1. // ES6  

  2. $("#confetti-btn").click(event => {  

  3.   playTrumpet();  

  4.   fireConfettiCannon();  

  5. });  


this是什么?

普通函数与箭头函数有个微小的不同点。箭头函数没有自己的this值,其this值是通过继承其它传入对象而获得的。

JS是如何处理this的呢?这可不是个简单的问题。其中不论函数有没有真的需要处理this,函数都是会接收到的。你曾经写过如下代码吗?


[js] view plaincopy

  1. {  

  2.   ...  

  3.   addAll: function addAll(pieces) {  

  4.     var self = this;  

  5.     _.each(pieces, function (piece) {  

  6.       self.add(piece);  

  7.     });  

  8.   },  

  9.   ...  

  10. }  


这里,其实你想写的内联函数仅仅是this.add(piece)。然而内联函数不会继承外部函数的this值。在内联函数中,this的值是window或undefined。临时变量self用于向内联函数传入外部this值。

在ES6中,如果遵循如下原则则可避免类似的做法:


  • 使用非箭头函数来处理由object.method()语法调用的方法。因为它们会接收到来自调用者的有意义的this值。

  • 在其它场合都使用箭头函数。



[js] view plaincopy

  1. // ES6  

  2. {  

  3.   ...  

  4.   addAll: function addAll(pieces) {  

  5.     _.each(pieces, piece => this.add(piece));  

  6.   },  

  7.   ...  

  8. }  


什么时候使用箭头函数

ES6箭头函数在Firefox、Babel、Traceur、TypeScript等项目都有使用。在1936年,Alonzo Church和Alan Turing一起开发了强大的数学计算机模型,人们习惯把它称为图灵机。Church编写了名为λ-calculus的模型,当时他发现需要在系统使用到“函数”。

这是一个结合Church想法的“程序”示例:


[js] view plaincopy

  1. fix = λf.(λx.f(λv.x(x)(v)))(λx.f(λv.x(x)(v)))  


JS中可表示为:


[js] view plaincopy

  1. var fix = f => (x => f(v => x(x)(v)))  

  2.                (x => f(v => x(x)(v)));  


这个故事告诉我们,箭头函数可以帮助打破陈规,从新的角度来思考问题。借助箭头函数,ES6将会变得更好更强大。


本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息