箭头函数是JavaScriptES6(ECMAScript 2015)引入的一项新特性,它提供了一种更简洁的函数表达式写法。这种函数使用一个新符号“=>”来定义,因此也被称为“胖箭头”函数。箭头函数是匿名的,并且改变了函数内部this
的绑定方式。
箭头函数的引入使得代码更加简洁,简化了函数作用域和this
关键字的使用。它们是一行的迷函数,类似于C#或Python中的Lambda表达式。使用箭头函数可以避免编写function
关键字、return
关键字(在箭头函数中是隐式的)以及大括号。
箭头函数,也称为“胖箭头”函数,源自CoffeeScript(一种转译语言),是一种更简洁的函数表达式写法。它们使用一个新的符号“=>”,看起来像一个胖箭头。箭头函数是匿名的,并且改变了函数内部this
的绑定方式。
箭头函数使得代码更加简洁,并且简化了函数作用域和this
关键字的使用。它们是一行的迷函数,类似于C#或Python中的Lambda表达式。通过使用箭头函数,避免了输入function
关键字、return
关键字(在箭头函数中是隐式的)以及大括号。
箭头函数有多种语法形式。EcmaScript.org和MDN都有详尽的语法列表。这里只介绍一些常见的语法,以帮助入门。
让比较一下ES5中使用函数表达式的代码如何用ES6中的箭头函数来重写。
如果箭头函数有多个参数,基本语法如下:
var multiply = (x, y) => x * y;
上述箭头函数示例允许开发者用更少的代码行数和大约一半的打字量来实现相同的结果。
如果只有一个参数,括号是可选的:
var greet = name => `Hello, ${name}!`;
如果没有参数,括号是必须的:
var sayHello = () => console.log('Hello!');
箭头函数可以像函数表达式一样用来返回一个对象字面量表达式。唯一的区别是,函数体需要用括号包裹起来,以便区分代码块和对象(两者都使用大括号)。
var getUserInfo = user => ({ name: user.name, age: user.age });
现在已经了解了基本语法,让看看箭头函数是如何被使用的。
箭头函数的一个常见用例是数组操作。例如,可能需要映射或归并一个数组。考虑以下简单的对象数组:
var smartPhones = [
{ name: 'iPhone', price: 649 },
{ name: 'Galaxy S6', price: 576 },
{ name: 'Galaxy Note 5', price: 489 }
];
在ES5中,可以通过以下方式创建一个只包含名称或价格的对象数组:
console.log(smartPhones.map(function(smartPhone) {
return smartPhone.price;
}));
// [649, 576, 489]
使用箭头函数,代码更加简洁且易于阅读:
console.log(smartPhones.map(smartPhone => smartPhone.price));
// [649, 576, 489]
this
含义使用箭头函数的另一个好处是减少了围绕this
关键字的混淆。在包含多个嵌套函数的代码中,跟踪并记住绑定正确的this
上下文可能会很困难。在ES5中,可以使用诸如.bind方法(这很慢)或创建一个闭包var self = this;
等变通方法。
因为箭头函数允许在函数内部保留调用者的上下文,所以不需要创建self = this
闭包或使用bind。
开发者Jack Franklin提供了一个使用箭头函数词法this
来简化Promise的优秀实用示例:
API.prototype.get = function(resource) {
var self = this;
return new Promise(function(resolve, reject) {
http.get(self.uri + resource, function(data) {
resolve(data);
});
});
};
使用箭头函数,同样的结果可以更简洁、清晰地实现:
API.prototype.get = function(resource) {
return new Promise((resolve, reject) => {
http.get(this.uri + resource, function(data) {
resolve(data);
});
});
};
新的箭头函数为ECMAScript带来了有用的函数语法,但与任何新特性一样,它们也有自己的陷阱和缺陷。
JavaScript开发者和作家Kyle Simpson认为箭头函数的陷阱足够多,以至于他制作了一个流程图来决定何时使用它们。他认为箭头函数的规则/语法太多,令人困惑。其他人则认为,使用箭头函数可以节省打字,但最终会使代码更难阅读。所有那些function
和return
语句可能会使阅读多个嵌套函数或一般的函数表达式变得更容易。
开发者对几乎所有事情的看法都各不相同,包括箭头函数。为了简洁起见,这里有一些使用箭头函数时需要注意的事情。
如前所述,箭头函数中的this
关键字的工作原理不同。方法call()
、apply()
和bind()
不会改变箭头函数中this
的值。(实际上,函数内部的this
值不能改变——它将与函数被调用时的值相同。)如果需要绑定到不同的值,需要使用函数表达式。
箭头函数不能像其他函数那样用作构造函数。不要使用它们来创建类似对象的对象。如果尝试使用new
与箭头函数,它将抛出一个错误。箭头函数,像内置函数(即方法)一样,没有原型属性或其他内部方法。因为构造函数通常用于在JavaScript中创建类似的对象,所以应该使用新的ES6类。
箭头函数被设计为轻量级,不能用作生成器。在ES6中使用yield
关键字将抛出一个错误。使用ES6生成器代替。
箭头函数没有其他函数那样的局部变量参数。参数对象是一个类似数组的对象,允许开发者动态地发现和访问函数的参数。这很有帮助,因为JavaScript函数可以接收无限数量的参数。箭头函数没有这个对象。
箭头函数被称为ES6中最快的胜利之一。开发者Lars Schöning展示了他的团队决定在哪里使用箭头函数:
在全局作用域和Object.prototype属性中使用function。
使用class作为对象构造函数。
在其他地方使用=>
箭头函数,像let和const一样,可能会成为默认的函数,除非需要函数表达式或声明。为了了解箭头函数的使用频率,Kevin Smith计算了各种流行库/框架中的函数表达式,并发现大约55%的函数表达式是箭头函数的候选。
箭头函数已经到来(来吧,Safari!)——它们功能强大、简洁,开发者喜欢它们。也许是时候开始使用它们了!