A while ago our team migrated all its code (a mid-sized AngularJS app) to JavaScript compiled using
Traceur
Babel .
(不久前,我们的团队将其所有代码(中型AngularJS应用程序)迁移到了使用
Traceur
Babel编译的JavaScript。)
I'm now using the following rule of thumb for functions in ES6 and beyond:(我现在对ES6及更高版本中的功能使用以下经验法则:)
Why use arrow functions almost everywhere?
(为什么几乎在所有地方都使用箭头功能?)
- Scope safety: When arrow functions are used consistently, everything is guaranteed to use the same
thisObject
as the root.(范围安全性:始终使用箭头功能时,可以确保所有内容都使用与根相同的thisObject
。)
If even a single standard function callback is mixed in with a bunch of arrow functions there's a chance the scope will become messed up.(如果什至将单个标准函数回调与一堆箭头函数混在一起,则范围可能会混乱。)
- Compactness: Arrow functions are easier to read and write.
(紧凑性:箭头功能更易于读写。)
(This may seem opinionated so I will give a few examples further on).((这似乎是自以为是的,所以我将进一步举例说明)。)
- Clarity: When almost everything is an arrow function, any regular
function
immediately sticks out for defining the scope.(清晰度:当几乎所有功能都是箭头功能时,任何常规function
立即突出来定义范围。)
A developer can always look up the next-higher function
statement to see what the thisObject
is.(开发人员始终可以查找更高一级的function
语句,以查看thisObject
是什么。)
Why always use regular functions on the global scope or module scope?
(为什么总是在全局作用域或模块作用域上使用常规函数?)
- To indicate a function that should not access the
thisObject
.(指示不应访问thisObject
的函数。)
- The
window
object (global scope) is best addressed explicitly.(最好明确地处理window
对象(全局范围)。)
- Many
Object.prototype
definitions live in the global scope (think String.prototype.truncate
etc.) and those generally have to be of type function
anyway.(许多Object.prototype
定义都位于全局范围内(请考虑String.prototype.truncate
等),并且无论如何,这些定义通常必须是类型function
。)
Consistently using function
on the global scope helps avoid errors.(在全局范围内一致使用function
有助于避免错误。)
- Many functions in the global scope are object constructors for old-style class definitions.
(全局范围内的许多函数都是旧式类定义的对象构造函数。)
- Functions can be named 1 .
(函数可以命名为1 。)
This has two benefits: (1) It is less awkward to write function foo(){}
than const foo = () => {}
— in particular outside other function calls.(这有两个好处:(1)与const foo = () => {}
相比,编写function foo(){}
更为const foo = () => {}
—特别是在其他函数调用之外。)
(2) The function name shows in stack traces.((2)函数名称显示在堆栈跟踪中。)
While it would be tedious to name every internal callback, naming all the public functions is probably a good idea.(虽然命名每个内部回调很麻烦,但是命名所有公共函数可能是一个好主意。)
- Function declarations are hoisted , (meaning they can be accessed before they are declared), which is a useful attribute in a static utility function.
(函数声明是悬挂式的 (意味着可以在声明之前对其进行访问),这是静态实用程序函数中的一个有用属性。)
Object constructors
(对象构造函数)
Attempting to instantiate an arrow function throws an exception:
(尝试实例化箭头函数会引发异常:)
var x = () => {};
new x(); // TypeError: x is not a constructor
One key advantage of functions over arrow functions is therefore that functions double as object constructors:
(因此,与箭头函数相比,函数的一个关键优势是该函数还可以兼用作对象构造函数:)
function Person(name) {
this.name = name;
}
However, the functionally identical 2 ES Harmony draft class definition is almost as compact:
(但是,功能上相同的2 ES Harmony 草案类定义几乎一样紧凑:)
class Person {
constructor(name) {
this.name = name;
}
}
I expect that use of the former notation will eventually be discouraged.
(我希望最终不鼓励使用前一种表示法。)
The object constructor notation may still be used by some for simple anonymous object factories where objects are programmatically generated, but not for much else.(有些对象仍可以将对象构造函数表示法用于简单的匿名对象工厂,在这些工厂中以编程方式生成对象,而其他方面则不多。)
Where an object constructor is needed one should consider converting the function to a class
as shown above.
(在需要对象构造函数的地方,应考虑将函数转换为如上所述的class
。)
The syntax works with anonymous functions/classes as well.(该语法也可用于匿名函数/类。)
Readability of arrow functions
(箭头功能的可读性)
The probably best argument for sticking to regular functions - scope safety be damned - would be that arrow functions are less readable than regular functions.
(坚持使用常规功能最好的论据(该死的示波器安全性)将是,箭头功能不如常规功能易读。)
If your code is not functional in the first place, then arrow functions may not seem necessary, and when arrow functions are not used consistently they look ugly.(如果您的代码最初没有功能,那么箭头功能似乎就不是必需的,并且当箭头功能未得到一致使用时,它们看起来很丑陋。)
ECMAScript has changed quite a bit since ECMAScript 5.1 gave us the functional Array.forEach
, Array.map
and all of these functional programming features that have us use functions where for-loops would have been used before.
(自ECMAScript 5.1为我们提供了功能Array.forEach
, Array.map
以及所有这些功能性编程功能(使我们使用以前曾使用过for循环的功能)以来,ECMAScript发生了很大变化。)
Asynchronous JavaScript has taken off quite a bit.(异步JavaScript已经发展了很多。)
ES6 will also ship a Promise
object, which means even more anonymous functions.(ES6还将提供Promise
对象,这意味着甚至更多的匿名功能。)
There is no going back for functional programming.(函数式编程无可奈何。)
In functional JavaScript, arrow functions are preferable over regular functions.(在功能性JavaScript中,箭头功能优于常规功能。)
Take for instance this (particularly confusing) piece of code 3 :
(以这段(特别是令人困惑的)代码3为例:)
function CommentController(articles) {
this.comments = [];
articles.getList()
.then(articles => Promise.all(articles.map(article => article.comments.getList())))
.then(commentLists => commentLists.reduce((a, b) => a.concat(b)));
.then(comments => {
this.comments = comments;
})
}
The same piece of code with regular functions:
(具有常规功能的同一段代码:)
function CommentController(articles) {
this.comments = [];
articles.getList()
.then(function (articles) {
return Promise.all(articles.map(function (article) {
return article.comments.getList();
}));
})
.then(function (commentLists) {
return commentLists.reduce(function (a, b) {
return a.concat(b);
});
})
.then(function (comments) {
this.comments = comments;
}.bind(this));
}
While any one of the arrow functions can be replaced by a standard function, there would be very little to gain from doing so.
(虽然任何箭头功能都可以用标准功能代替,但这样做几乎没有好处。)
Which version is more readable?(哪个版本更具可读性?)
I would say the first one.(我会说第一个。)
I think the question whether to use arrow functions or regular functions will become less relevant over time.
(我认为是使用箭头功能还是使用常规功能的问题随着时间的推移将变得越来越不重要。)
Most functions will either become class methods, which make away with the function
keyword, or they will become classes.(大多数函数要么成为类方法,而这些方法不再使用function
关键字,要么成为类。)
Functions will remain in use for patching classes through the Object.prototype
.(函数将继续用于通过Object.prototype
修补类。)
In the mean time I suggest reserving the function
keyword for anything that should really be a class method or a class.(同时,我建议为实际上应该是类方法或类的任何内容保留function
关键字。)
Notes
(笔记)
- Named arrow functions have been deferred in the ES6 spec .
(ES6规范中已推迟了命名箭头功能。)
They might still be added a future version.(他们可能仍会添加将来的版本。)
- According to the draft specification "Class declarations/expressions create a constructor function/prototype pair exactly as for function declarations" as long as a class does not use the
extend
keyword.(根据规范草案“只要类不使用extend
关键字, “类声明/表达式将创建与函数声明完全相同的构造函数/原型” 。)
A minor difference is that class