首页 > 语言 > JavaScript > 正文

深入理解JavaScript中的箭头函数

2024-05-06 16:23:55
字体:
来源:转载
供稿:网友

这篇文章主要介绍了深入理解JavaScript中的箭头函数,文中主要针对ES6版本的JS进行相关的讲解,需要的朋友可以参考下

从一开始箭头就是 JavaScript 的一部分,在第一个 JavaScript 中就建议将内联的脚本代码包裹在 HTML 的注释中,这可以防止那些不支持 JavaScript 的浏览器错误滴将你的代码显示为明文。你也许写过下面这样的代码:

 

 
  1. <script language="javascript"
  2. <!-- 
  3. document.bgColor = "brown"// red 
  4. // --> 
  5. </script> 
  6.  
  7. <script language="javascript"
  8. <!-- 
  9. document.bgColor = "brown"// red 
  10. // --> 
  11. </script> 

古老的浏览器将看到两个不被支持的标签和一段注释,只有支持 JavaScript 的新浏览器才会将其解析为 JavaScript 代码。

为了支持这个古怪的特性,浏览器的 JavaScript 引擎把 也表示一个单行注释,与 HTML 不同的是,在 HTML 中,--> 之前的部分是注释内容,而在 JavaScript 中,在 --> 之后的行才是注释。

只有当 --> 出现在一行的开始时,才表示该箭头是一个注释,因为在其他情况下,--> 是一个操作符(goes to)。

 

 
  1. function countdown(n) { 
  2. while (n-->0) // "n goes to zero" 
  3. alert(n); 
  4. blastoff(); 
  5.  
  6. function countdown(n) { 
  7. while (n-->0) // "n goes to zero" 
  8. alert(n); 
  9. blastoff(); 

上面代码是真实能运行的。循环运行直到 n 为 0,这并不是 ES6 的新特性,但结合我们熟悉的特性,这具有很强的误导性。你能搞明白上面代码的运行情况吗?你可以在 Stack Overflow 上找到相应的解答。

当然还有一个箭头,那就是小于等于操作符 <=,也许你还可以找到使用箭头的地方,但我们还是停下来,看一个我们从没见过的箭头:

goes to 操作符

<= 小于等于操作符

=> ???

那么,=> 表示什么呢?这就是本文将讨论的话题。

首先,我们来谈谈函数。

无处不在的函数表达式

JavaScript 一个有趣的特点是,任何时候你需要一个函数,你可以很方便地创建它们。

例如,为一个按钮绑定点击事件:

 

 
  1. $("#confetti-btn").click( 
  2.  
  3. $("#confetti-btn").click( 

jQuery 的 .click() 方法需要一个函数作为参数,我们可以很方便地就地创建一个函数:

 

 
  1. $("#confetti-btn").click(function (event) { 
  2. playTrumpet(); 
  3. fireConfettiCannon(); 
  4. }); 
  5.  
  6.  
  7. $("#confetti-btn").click(function (event) { 
  8. playTrumpet(); 
  9. fireConfettiCannon(); 
  10. }); 

现在对我们来说,编写这样的代码是最自然的事了。但是在 JavaScript 流行起来之前,这种风格的代码看起来还是有些奇怪,因为在其他语言中都没有这样的特性。在 1958 年,Lisp 就有了函数表达式,也叫 lambda 函数,而在存在多年的 C++、Python、C# 和 Java 中没有该特性。

现在,这四门语言都有了 lambda 表达式,而且新出现的语言都普遍内置了 lambda 表达式。如今 JavaScript 也支持该特性了,这必须感谢那些重度依赖 lambda 表达式的库的开发者,这推动了该特性被广泛采纳。

与其他几门语言相比,JavaScript 的语法略显冗长:

 

 
  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 
  8.  
  9. // A very simple function in six languages. 
  10. function (a) { return a > 0; } // JS 
  11. [](int a) { return a > 0; } // C++ 
  12. (lambda (a) (> a 0)) ;; Lisp 
  13. lambda a: a > 0 # Python 
  14. a => a > 0 // C# 
  15. a -> a > 0 // Java 

箭头函数

ES6 引入了一种新的语法来编写函数:

 

 
  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()); 
  8.  
  9.  
  10. // ES5 
  11. var selected = allJobs.filter(function (job) { 
  12. return job.isSelected(); 
  13. }); 
  14.  
  15. // ES6 
  16. var selected = allJobs.filter(job => job.isSelected()); 

当你需要只有一个参数的函数,箭头函数的语法可以简化为 Identifier => Expression,直接省略了 function 和 return 关键字,连括号和结尾的分号也同时省略了。

编写一个有多个(或没有参数,或 Rest 参数和参数默认值,或解构参数)参数的函数,你需要用括号将参数括起来:

 

 
  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); 
  8.  
  9. // ES5 
  10. var total = values.reduce(function (a, b) { 
  11. return a + b; 
  12. }, 0); 
  13.  
  14. // ES6 
  15. var total = values.reduce((a, b) => a + b, 0); 

箭头函数还可以与一些工具函数库完美地配合使用,比如 Underscore.js 和 Immutable,事实上,Immutable 文档中的例子全部都是使用 ES6 编写,其中有很多已经使用到了箭头函数。

函数体除了使用一个表达式外,箭头函数还可以包含一个语句块,回忆之前我们提到过的例子:

 

 
  1. // ES5 
  2. $("#confetti-btn").click(function (event) { 
  3. playTrumpet(); 
  4. fireConfettiCannon(); 
  5. }); 
  6.  
  7. // ES5 
  8. $("#confetti-btn").click(function (event) { 
  9. playTrumpet(); 
  10. fireConfettiCannon(); 
  11. }); 

下面是采用箭头函数的写法:

 

 
  1. // ES6 
  2. $("#confetti-btn").click(event => { 
  3. playTrumpet(); 
  4. fireConfettiCannon(); 
  5. }); 
  6.  
  7. // ES6 
  8. $("#confetti-btn").click(event => { 
  9. playTrumpet(); 
  10. fireConfettiCannon(); 
  11. }); 

需要注意的是,使用语句块的箭头函数不会自动返回一个值,必须显式地使用 return 来返回一个值。

还有一个忠告,当使用箭头函数来返回一个对象时,始终使用括号将返回的对象括起来:

 

 
  1. // create a new empty object for each puppy to play with 
  2. var chewToys = puppies.map(puppy => {}); // BUG! 
  3. var chewToys = puppies.map(puppy => ({})); // ok 
  4.  
  5.  
  6. // create a new empty object for each puppy to play with 
  7. var chewToys = puppies.map(puppy => {}); // BUG! 
  8. var chewToys = puppies.map(puppy => ({})); // ok 

因为空对象 {} 与空语句块 {} 看上去一模一样,ES6 将始终把紧跟在 => 后面的 { 当作语句块的开始,而不是一个对象的开始,那么 puppy => {} 就被解析为一个没有函数体的箭头函数,而且返回值为 undefined。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选