文章目录
❗ 本文最后更新于 4088 天前,文中所描述的信息可能已发生改变,请谨慎使用。
最近组里不少同学对 ES6 很有兴趣,月影老大也给大家分享过有关 ES6 的话题。接下来,我也会尝试使用 ES6 的一些新特性并记录下来,内容不一定全面或精确。更全面的 ES6 介绍可以参考相应标准文档,或者MDN,或者有大量高质量 ES6 译文及原创的优秀博客紫云飞。另外,「奇舞周刊」近期准备开辟译文专栏,有兴趣参与的同学请联系我。
废话不多说,今天要介绍的是 ES6 中的箭头函数(Arrow Function),目前只有 Firefox22+ 支持,本文示例需要在新版 Firefox 下才能正常工作。
定义
定义一个箭头函数很简单,基本语法是:
([param] [, param]) => {
statements
}
param => expression
param 是参数,根据参数个数不同,分这几种情况:
- () => { ... } // 零个参数用 () 表示;
- x => { ... } // 一个参数可以省略 ();
- (x, y) => { ... } // 多参数不能省略 ();
当然,和普通函数一样,箭头函数也可以使用 ES6 新增的「默认参数」和「剩余参数」( Firefox15+ 开始支持):
var func1 = (x = 1, y = 2) => x + y;
func1(); // 得到 3
var func2 = (x, ...args) => { console.log(args) };
func2(1,2,3); // 输出 [2, 3]
箭头函数允许多行语句或者单行表达式作为函数体。多行语句要用 {} 括起来;单行表达式不需要 {},并且会作为函数返回值:
x => { return x * x }; // 函数返回 x * x
x => x * x; // 同上一行
x => return x * x; // SyntaxError 报错,不能省略 {}
x => { x * x }; // 合法,没有定义返回值,返回 undefined
箭头函数也是 JS 函数的一种,所以之前的 instanceof 和 typeof 依然可用:
var func1 = () => {};
func1 instanceof Function; // true
var func2 = () => {};
typeof func2; // "function"
特性
Nicholas C. Zakas 的博客中指出了箭头函数的几个特性:不能被 new 、this 被绑定为函数定义时的 this 且无法改变、不支持 arguments 。对于最后一点,我在 Firefox24 测试发现,arguments 可以正常工作。不知道是标准有变化,还是 Firefox 的实现有偏差,我们来看前两个特性。
箭头函数内部没有 constructor 方法,也没有 prototype,所以不支持 new 操作。new (() => {}) 会触发 TypeError 报错。
JS 里的 this 指针一直是新手很头疼的事情,看一个简单的例子:
var o = {
x : 1,
func : function() { console.log(this.x) },
test : function() {
setTimeout(function() {
this.func();
}, 100);
}
};
o.test(); // TypeError : this.func is not a function
上面代码得不到预期结果,因为 this 发生了改变,这个问题可以这样修正:
var o = {
x : 1,
func : function() { console.log(this.x) },
test : function() {
var _this = this;
setTimeout(function() {
_this.func();
}, 100);
}
};
o.test();
在函数内部使用外部事先保存的 this 就没问题了。也可以改用 ES5 引入的 bind 方法:
var o = {
x : 1,
func : function() { console.log(this.x) },
test : function() {
setTimeout(function() {
this.func();
}.bind(this), 100);
}
};
o.test();
而有了箭头函数,像下面这样写就可以了:
var o = {
x : 1,
func : function() { console.log(this.x) },
test : function() {
setTimeout(() => { this.func() }, 100);
}
};
o.test();
箭头函数的 this 始终指向函数定义时的 this,而非执行时。下面看一个尝试改变箭头函数 this 指针的例子:
var x = 1,
o = {
x : 10,
test : () => this.x
};
o.test(); // 1
o.test.call(o); // 依然是1
CoffeeScript
实际上,CoffeeScript 一直就支持用这种 =>(胖箭头)定义函数;同时 CoffeeScript 还支持用 ->(瘦箭头)定义函数。二者的区别是胖箭头会绑定 this,瘦箭头不会,来看一个例子,以下是 Coffee 代码:
this.clickHandler = -> alert "clicked"
el1.addEventListener "click", (e) => this.clickHandler(e)
el2.addEventListener "click", (e) -> this.clickHandler(e)
编译后的 JS 代码是这样的:
var _this = this;
this.clickHandler = function() {
return alert("clicked");
};
el1.addEventListener("click", function(e) {
return _this.clickHandler(e);
});
el2.addEventListener("click", function(e) {
return this.clickHandler(e);
});
可以看到,使用胖箭头的 el1 绑定的 click 函数的 this 指向函数定义时的 this;而 el2 的 click 函数的 this 指向运行时的元素本身。
JS 的箭头函数没看到有瘦箭头的形式。
性能
关于箭头函数的性能,我不想花精力去研究。一方面 ES6 标准并没有完全确定,另一方面现在只有 Firefox 一家支持箭头函数,对比意义不大。jsPref 上有个相关的测试,大家可以点过去看看。从已有的结果来看,箭头函数与 bind 函数对比,性能差别不大;尤其是在 Firefox25 上,箭头函数已经比 bind 快了。
参考:
- Understanding ECMAScript 6 arrow functions (中文翻译)
- ECMAScript.next: arrow functions and method definitions
- 箭头函数 - JavaScript | MDN
本文链接:https://mailseason.com/post/arrow-function-in-es6.html,参与评论 »
--EOF--
发表于 2013-09-11 22:22:35,并被添加「ES6、JavaScript」标签。查看本文 Markdown 版本 »
专题「JavaScript 漫谈」的其他文章 »
- 改进 ThinkJS 的异步编程方式 (May 15, 2015)
- BOM 和 JavaScript 中的 trim (Dec 07, 2013)
- AMD 的 CommonJS wrapping (Dec 05, 2013)
- FileSystem API 实现文件下载器 2 (Oct 01, 2013)
- 用 FileSystem API 实现文件下载器 (Oct 01, 2013)
- ES6 中的 Set、Map 和 WeakMap (Sep 23, 2013)
- ES6 中的生成器函数介绍 (Sep 20, 2013)
- 使用 Canvas 绘制背景图 (Aug 18, 2013)
- 异步编程:When.js快速上手 (Jun 23, 2013)
- JavaScript动画漫谈 (Nov 15, 2012)
Comments
Waline 评论加载中...