JavaScript ES6 箭头函数:语法、this 绑定与注意事项

作者:拾光时间:2026-10-22 19:58:18浏览:178

本文深入解析 ES6 箭头函数的核心特性,包括其简洁的语法糖、自动继承父级 this 上下文以及不支持 arguments 和 generator 的限制。通过对比传统函数与 Promise 链示例,阐明单行隐式返回、空对象返回陷阱及 rest 参数用法,帮助开发者正确使用箭头函数优化代码。

胖箭头函数(Fat arrow functions),即箭头函数,是 ECMAScript 2015(ES6)引入的一项新特性。据传其语法符号 => 借鉴自 CoffeeScript,两者在共享 this 上下文方面具有相似性。

箭头函数的设计主要出于两个目的:提供更简洁的语法结构,以及与父级作用域共享关键字 this。下文将通过具体示例进行详细说明。

新的函数语法

新的函数语法

传统的 JavaScript 函数语法在灵活性上有所欠缺,每次定义函数时都必须输入 function () {}。CoffeeScript 之所以流行,部分原因在于其更简洁的函数语法。在涉及大量回调函数的场景中,这种简洁性优势尤为明显,以下通过一个 Promise 链示例进行展示:


function getVerifiedToken(selector) {
 return getUsers(selector)
  .then(function (users) { return users[0]; })
  .then(verifyUser)
  .then(function (user, verifiedToken) { return verifiedToken; })
  .catch(function (err) { log(err.stack); });
}

以下是使用新的箭头函数语法重构后的代码:


function getVerifiedToken(selector) {
 return getUsers(selector)
  .then(users => users[0])
  .then(verifyUser)
  .then((user, verifiedToken) => verifiedToken)
  .catch(err => log(err.stack));
}

以下是值得注意的几个要点:

function 关键字和 {} 大括号均已消失,所有回调函数均压缩至单行显示。当函数仅有一个参数时,() 小括号也可省略(rest 参数如 (...args) => ... 除外)。当 {} 大括号消失后,return 关键字也随之省略。单行箭头函数会提供隐式的 return 值(此类函数在其他编程语言中常被称为 lambda 函数)。此处需重点强调:仅当箭头函数为单行形式时,才会出现隐式 return。若箭头函数声明时包含 {} 大括号,即使代码仅有一行,也不会产生隐式 return:


const getVerifiedToken = selector => {
 return getUsers()
  .then(users => users[0])
  .then(verifyUser)
  .then((user, verifiedToken) => verifiedToken)
  .catch(err => log(err.stack));
}

若函数体内仅包含一条语句(statement),可不写 {} 大括号,此时其外观与 CoffeeScript 中的函数非常相似:


const getVerifiedToken = selector =>
 getUsers()
  .then(users => users[0])
  .then(verifyUser)
  .then((user, verifiedToken) => verifiedToken)
  .catch(err => log(err.stack));

以上示例完全符合 ES6 语法规范。需要注意的是,当讨论仅包含一条语句的箭头函数时,该语句本身仍可跨多行书写。

这里存在一个常见陷阱:当省略 {} 大括号后,如何返回空对象({})?


const emptyObject = () => {};
emptyObject(); // ?

由于空对象 {} 与空白函数代码块 {} 外观一致,上述示例中 emptyObject 的 {} 会被解释为空白函数代码块,导致 emptyObject() 返回 undefined。若要在箭头函数中明确返回空对象,必须将 {} 包裹在一对圆括号中 (({})):


const emptyObject = () => ({});
emptyObject(); // {}

下面是一个更完整的对比示例:


function () { return 1; }
() => { return 1; }
() => 1
 
function (a) { return a * 2; }
(a) => { return a * 2; }
(a) => a * 2
a => a * 2
 
function (a, b) { return a * b; }
(a, b) => { return a * b; }
(a, b) => a * b
 
function () { return arguments[0]; }
(...args) => args[0]
 
() => {} // undefined
() => ({}) // {}

this 上下文

this 上下文

JavaScript 中 this 的指向问题由来已久,每个函数都有其独立的上下文。以下示例旨在使用 jQuery 展示一个每秒更新的时钟:


$('.current-time').each(function () {
 setInterval(function () {
  $(this).text(Date.now());
 }, 1000);
});

当尝试在 setInterval 的回调中使用 this 引用 DOM 元素时,不幸的是,得到的只是属于回调函数自身上下文的 this。通常的解决办法是定义一个 that 或 self 变量来保存外层 this:


$('.current-time').each(function () {
 var self = this;
 
 setInterval(function () {
  $(self).text(Date.now());
 }, 1000);
});

然而,使用胖箭头函数时,此问题不再存在。因为箭头函数不产生属于它自己的 this 上下文,而是继承外层:


$('.current-time').each(function () {
 setInterval(() => $(this).text(Date.now()), 1000);
});

arguments 变量

arguments 变量

箭头函数与普通函数的另一区别在于,它没有自己的 arguments 变量:


function log(msg) {
 const print = () => console.log(arguments[0]);
 print(`LOG: ${msg}`);
}
 
log('hello'); // hello

再次重申,箭头函数既没有属于自己的 this,也没有 arguments。但可以通过 rest 参数获取所有传入参数的数组:


function log(msg) {
 const print = (...args) => console.log(args[0]);
 print(`LOG: ${msg}`);
}
 
log('hello'); // LOG: hello

关于 yield

关于 yield

箭头函数不能作为 generator 函数使用。

最后

箭头函数是我最喜欢的 ES6 特性之一。使用 => 代替 function 非常便捷。但也曾见过仅使用 => 声明函数的代码,我并不认为这是最佳实践,因为 => 提供了区别于传统 function 的独特特性。个人建议:仅在你需要使用其提供的新特性时,才使用箭头函数:

当只有一条语句(statement)时,支持隐式 return。 需要使用到父作用域中的 this。

本文详细说明了 JavaScript ES6 新特性之一的箭头函数的使用方法和一些注意事项,大家在使用时一定要注意,箭头函数用好了是非常快捷的,如果用不好的话也是非常令人头痛的

作者最新文章