JavaScript ES6箭头函数使用指南


Posted in Javascript onDecember 30, 2018

胖箭头函数(Fat arrow functions),又称箭头函数,是一个来自ECMAScript 2015(又称ES6)的全新特性。有传闻说,箭头函数的语法=>,是受到了CoffeeScript 的影响,并且它与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(这样的函数在其他编程语言中常被成为lamda函数)。
这里再着重强调一下上述的最后一个要求。仅仅当箭头函数为单行的形式时,才会出现隐式的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语法。当我们谈论只包含一条声明(statement)的箭头函数时,这并不意味着这条声明不能够分成多行写。

这里有一个坑,当忽略了{}后,我们该怎么返回空对象({})呢?

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

JavaScript中this的故事已经是非常古老了,每一个函数都有自己的上下文。以下例子的目的是使用jQuery来展示一个每秒都会更新的时钟:

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

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

$('.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变量:

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

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

最后

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

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

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

Javascript 相关文章推荐
ASP.NET中使用后端代码注册脚本 生成JQUERY-EASYUI的界面错位的解决方法
Jun 12 Javascript
jqPlot 基于jquery的画图插件
Apr 26 Javascript
Jquery代码实现图片轮播效果(一)
Aug 12 Javascript
JavaScript Base64 作为文件上传的实例代码解析
Feb 14 Javascript
javascript事件的绑定基础实例讲解(34)
Feb 14 Javascript
jQuery事件详解
Feb 23 Javascript
JQuery实现图片轮播效果
May 08 jQuery
angularjs2中父子组件的数据传递的实例代码
Jul 05 Javascript
Angular 2使用路由自定义弹出组件toast操作示例
May 10 Javascript
如何实现小程序tab栏下划线动画效果
May 18 Javascript
如何在wxml中直接写js代码(wxs)
Nov 14 Javascript
JavaScript检测是否开启了控制台(F12调试工具)
Oct 02 Javascript
JavaScript创建防篡改对象的方法分析
Dec 30 #Javascript
JavaScript事件对象深入详解
Dec 30 #Javascript
JavaScript继承的特性与实践应用深入详解
Dec 30 #Javascript
JavaScript函数的特性与应用实践深入详解
Dec 30 #Javascript
基于Three.js实现360度全景图片
Dec 30 #Javascript
three.js实现圆柱体
Dec 30 #Javascript
three.js实现炫酷的全景3D重力感应
Dec 30 #Javascript
You might like
PHP+DBM的同学录程序(1)
2006/10/09 PHP
PHP中VC6、VC9、TS、NTS版本的区别与用法详解
2013/10/26 PHP
php和jquery实现地图区域数据统计展示数据示例
2014/02/12 PHP
php操作xml入门之cdata区段
2015/01/23 PHP
PHP微信红包生成代码分享
2016/10/06 PHP
php与python实现的线程池多线程爬虫功能示例
2016/10/12 PHP
PHP+JS实现的商品秒杀倒计时用法示例
2016/11/15 PHP
PHP随机获取未被微信屏蔽的域名(微信域名检测)
2017/03/19 PHP
PHP文字转图片功能原理与实现方法分析
2017/08/31 PHP
JS+CSS实现美化的下拉列表框效果
2015/08/11 Javascript
浅析JS获取url中的参数实例代码
2016/06/14 Javascript
基于cssSlidy.js插件实现响应式手机图片轮播效果
2016/08/30 Javascript
ES6中Array.copyWithin()函数的用法实例详解
2017/09/16 Javascript
Weex开发之WEEX-EROS开发踩坑(小结)
2019/10/16 Javascript
微信小程序清空输入框信息与实现屏幕往上滚动的示例代码
2020/06/23 Javascript
跟老齐学Python之数据类型总结
2014/09/24 Python
python中__slots__用法实例
2015/06/04 Python
Python的面向对象编程方式学习笔记
2016/07/12 Python
Python多版本开发环境管理工具介绍
2019/07/03 Python
Python求离散序列导数的示例
2019/07/10 Python
使用python telnetlib批量备份交换机配置的方法
2019/07/25 Python
Django框架HttpResponse对象用法实例分析
2019/11/01 Python
matplotlib阶梯图的实现(step())
2021/03/02 Python
使用CSS3来匹配横屏竖屏的简单方法
2015/08/04 HTML / CSS
前端实现打印图像功能
2019/08/27 HTML / CSS
canvas实现手机的手势解锁的步骤详细
2020/03/16 HTML / CSS
重新定义牛仔布,100美元以下:Warp + Weft
2018/07/25 全球购物
英国领先的互联网葡萄酒礼品商:Vintage Wine & Port
2019/05/24 全球购物
静态变量和实例变量的区别
2015/07/07 面试题
“四风”问题整改措施和努力方向
2014/09/20 职场文书
三人合伙协议书范本
2014/10/29 职场文书
会计岗位职责范本
2015/04/02 职场文书
2015年社区重阳节活动总结
2015/07/30 职场文书
html+css实现环绕倒影加载特效
2021/07/07 HTML / CSS
Linux中文件的基本属性介绍
2022/06/01 Servers
Linux在两个服务器直接传文件的操作方法
2022/08/05 Servers