深入理解JavaScript中的箭头函数

作者:拾光

时间:2026-10-29

浏览:466

本文深入解析JavaScript中的箭头函数(=>),从早期浏览器的兼容代码历史讲起,对比传统函数表达式与ES6语法,详细说明单参数简化写法、多参数括号用法及对象返回陷阱,帮助开发者掌握简洁高效的函数定义方式。

文章目录

JavaScript 中的箭头符号历史

JavaScript 自诞生之初便包含箭头元素。在早期规范中,建议将内联脚本包裹在 HTML 注释中,以阻止不支持 JavaScript 的浏览器将代码作为明文显示。你可能见过类似这样的代码结构。


<script language="javascript">
<!--
  document.bgColor = "brown"; // red
// -->
</script>
 
<script language="javascript">
<!--
  document.bgColor = "brown"; // red
// -->
</script>

旧版浏览器会识别出两个不被支持的标签以及一段注释内容,而支持 JavaScript 的现代浏览器则会将其正确解析为代码。

为了兼容这一特性,JavaScript 引擎将 <!-- 视为单行注释的起始符号。这并非玩笑,而是语言的一部分,至今仍然有效。它不仅适用于 <script> 标签的首行,还可出现在 JavaScript 代码的任何位置,甚至包括 Node.js 环境。

有趣的是,这种注释风格在 ES6 中得到了标准化。但这并非本文讨论的重点。

--> 同样表示单行注释。与 HTML 不同,HTML 中 --> 之前的内容是注释,而在 JavaScript 中,--> 之后的行才是注释内容。

只有当 --> 位于行首时,它才被视为注释;在其他情况下,--> 是一个操作符(goes to)。


function countdown(n) {
 while (n-->0) // "n goes to zero"
  alert(n);
 blastoff();
}
 
function countdown(n) {
 while (n-->0) // "n goes to zero"
  alert(n);
 blastoff();
}

上述代码是可以运行的。循环会一直执行直到 n 变为 0。这并非 ES6 的新特性,但结合其他熟悉的功能,容易让人产生误解。你能理解这段代码的运行逻辑吗?相关解答可在 Stack Overflow 上找到。

此外还有小于等于操作符 <=。虽然还能找到其他使用箭头符号的地方,但我们先暂停,看看一个全新的箭头符号:

  • <!-- 单行注释
  • --> goes to 操作符
  • <= 小于等于操作符
  •     => ???

那么,=> 代表什么?这正是本文要探讨的主题。

函数表达式与 Lambda 的发展

首先,我们来讨论函数。函数表达式无处不在。

JavaScript 的一个有趣特性是,当你需要函数时,可以非常方便地创建它们。

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


$("#confetti-btn").click(
 
$("#confetti-btn").click(

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


$("#confetti-btn").click(function (event) {
 playTrumpet();
 fireConfettiCannon();
});

 
$("#confetti-btn").click(function (event) {
 playTrumpet();
 fireConfettiCannon();
});

现在,编写这样的代码对我们来说已很自然。但在 JavaScript 流行之前,这种风格显得奇怪,因为其他语言当时没有此特性。1958 年的 Lisp 就有了函数表达式(即 lambda 函数),而 C++、Python、C# 和 Java 等存在多年的语言当时并未包含该特性。

如今,这四门语言都支持 lambda 表达式,新语言也普遍内置了这一特性。JavaScript 的支持得益于重度依赖 lambda 表达式的库开发者,这推动了该特性的广泛采纳。

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


// A very simple function in six languages.
function (a) { return a > 0; } // JS
[](int a) { return a > 0; } // C++
(lambda (a) (> a 0)) ;; Lisp
lambda a: a > 0 # Python
a => a > 0 // C#
a -> a > 0 // Java
 
// A very simple function in six languages.
function (a) { return a > 0; } // JS
[](int a) { return a > 0; } // C++
(lambda (a) (> a 0)) ;; Lisp
lambda a: a > 0 # Python
a => a > 0 // C#
a -> a > 0 // Java

ES6 箭头函数语法详解

箭头函数。

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


// ES5
var selected = allJobs.filter(function (job) {
 return job.isSelected();
});

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

 
// ES5
var selected = allJobs.filter(function (job) {
 return job.isSelected();
});
 
// ES6
var selected = allJobs.filter(job => job.isSelected());

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

编写包含多个(或无参数、Rest 参数、默认参数、解构参数)的函数时,需用括号将参数括起来。


// ES5
var total = values.reduce(function (a, b) {
 return a + b;
}, 0);

// ES6
var total = values.reduce((a, b) => a + b, 0);
 
// ES5
var total = values.reduce(function (a, b) {
 return a + b;
}, 0);
 
// ES6
var total = values.reduce((a, b) => a + b, 0);

箭头函数可与工具函数库(如 Underscore.js 和 Immutable)完美配合。事实上,Immutable 文档中的示例全部使用 ES6 编写,其中大量使用了箭头函数。

除了使用单个表达式,箭头函数还可以包含语句块。回顾之前提到的例子:


// ES5
$("#confetti-btn").click(function (event) {
 playTrumpet();
 fireConfettiCannon();
});
 
// ES5
$("#confetti-btn").click(function (event) {
 playTrumpet();
 fireConfettiCannon();
});

以下是采用箭头函数的写法。


// ES6
$("#confetti-btn").click(event => {
 playTrumpet();
 fireConfettiCannon();
});
 
// ES6
$("#confetti-btn").click(event => {
 playTrumpet();
 fireConfettiCannon();
});

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

返回对象的注意事项

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


// create a new empty object for each puppy to play with
var chewToys = puppies.map(puppy => {});  // BUG!
var chewToys = puppies.map(puppy => ({})); // ok

 
// create a new empty object for each puppy to play with
var chewToys = puppies.map(puppy => {});  // BUG!
var chewToys = puppies.map(puppy => ({})); // ok

因为空对象 {} 与空语句块 {} 外观相同,ES6 会将紧跟在 => 后的 { 视为语句块的开始,而非对象的开始。因此 puppy => {} 会被解析为一个没有函数体的箭头函数,返回值为 undefined。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章