根据该提案,箭头旨在“解决和解决传统功能表达的几个常见痛点”。他们打算通过绑定词汇和提供简洁的语法来改善问题。this
然而
- 一个人不能始终如一地在词汇上绑定
this
- 箭头函数语法细腻且模棱两可
因此,箭头函数会造成混淆和错误,应该从 JavaScript 程序员的词汇表中排除,代之以专用。function
关于词汇this
this
有问题:
function Book(settings) {
this.settings = settings;
this.pages = this.createPages();
}
Book.prototype.render = function () {
this.pages.forEach(function (page) {
page.draw(this.settings);
}, this);
};
Arrow 函数旨在解决我们需要访问回调内部属性的问题。已经有几种方法可以做到这一点:可以分配给变量,使用,或者使用聚合方法上可用的第三个参数。然而,箭头似乎是最简单的解决方法,因此该方法可以像这样重构:this
this
bind
Array
this.pages.forEach(page => page.draw(this.settings));
但是,请考虑代码是否使用了类似 jQuery 的库,其方法专门绑定。现在,有两个值需要处理:this
this
Book.prototype.render = function () {
var book = this;
this.$pages.each(function (index) {
var $page = $(this);
book.draw(book.currentPage + index, $page);
});
};
我们必须使用,以便动态绑定。我们不能在这里使用箭头函数。function
each
this
处理多个值也可能令人困惑,因为很难知道作者在谈论哪个:this
this
function Reader() {
this.book.on('change', function () {
this.reformat();
});
}
作者真的打算打电话吗?还是他忘了绑,打算打电话?如果我们将处理程序更改为箭头函数,我们同样会想知道作者是否想要动态,但选择了一个箭头,因为它适合一行:Book.prototype.reformat
this
Reader.prototype.reformat
this
function Reader() {
this.book.on('change', () => this.reformat());
}
有人可能会说:“箭头有时可能是错误的功能,这是否是例外?也许如果我们很少需要动态值,那么大多数时候使用箭头仍然是可以的。this
但是问问自己:“调试代码并发现错误的结果是由'边缘情况'引起的,这是否'值得'?我宁愿避免麻烦,不仅大部分时间,而且100%的时间。
有一个更好的方法:始终使用(因此始终可以动态绑定),并且始终通过变量引用。变量是词法的,并假定许多名称。赋值到变量将明确您的意图:function
this
this
this
function Reader() {
var reader = this;
reader.book.on('change', function () {
var book = this;
book.reformat();
reader.reformat();
});
}
此外,始终赋值给变量(即使存在单个函数或没有其他函数)可确保即使在代码更改后,其意图仍然清晰。this
this
此外,动态也并非异常。jQuery在超过5000万个网站上使用(截至2016年2月撰写本文时)。以下是动态绑定的其他 API:this
this
- Mocha(昨天下载量约为120k)通过.
this
- Grunt(昨天下载量约为63k)通过公开了构建任务的方法。
this
- Backbone(昨天下载量约为 22k)定义了访问 的方法。
this
- 事件 API(如 DOM 的)引用 with .
EventTarget
this
-
原型修补或扩展的 API 是指带有 的实例。
this
(通过 http://trends.builtwith.com/javascript/jQuery 和 https://www.npmjs.com 进行统计。
您可能已经需要动态绑定。this
有时需要一个词汇,但有时不是;就像动态有时是预期的,但有时不是。值得庆幸的是,有一种更好的方法,它总是产生和传达预期的绑定。this
this
关于简洁的语法
箭头函数成功地为函数提供了“更短的语法形式”。但是,这些较短的功能会让你更成功吗?
“更容易阅读”比?也许是这样,因为它更有可能产生一行短代码。根据戴森的《阅读速度和行长对屏幕阅读效果的影响》,x => x * x
function (x) { return x * x; }
中等行长(每行 55 个字符)似乎支持在正常和快速速度下的有效读取。这产生了最高水平的理解力。 。 。
对于条件(三元)运算符和单行语句,也进行了类似的论证。if
但是,你真的在写提案中宣传的简单数学函数吗?我的域不是数学的,所以我的子例程很少这么优雅。相反,我经常看到箭头函数打破了列限制,并由于编辑器或样式指南而换行到另一行,这根据戴森的定义使“可读性”无效。
有人可能会说,“如果可能的话,只使用短版本来做短功能怎么样?但现在,文体规则与语言约束相矛盾:“尝试使用尽可能短的函数表示法,请记住,有时只有最长的表示法才能按预期绑定。这种混杂使得箭头特别容易被误用。this
箭头函数语法存在许多问题:
const a = x =>
doSomething(x);
const b = x =>
doSomething(x);
doSomethingElse(x);
这两个函数在语法上都是有效的。但不在正文中。它只是一个缩进不良的顶级语句。doSomethingElse(x);
b
当扩展到块形式时,不再有一个隐式的,人们可能会忘记恢复。但是这个表达式可能只是为了产生副作用,所以谁知道未来是否需要显式表达呢?return
return
const create = () => User.create();
const create = () => {
let user;
User.create().then(result => {
user = result;
return sendEmail();
}).then(() => user);
};
const create = () => {
let user;
return User.create().then(result => {
user = result;
return sendEmail();
}).then(() => user);
};
可能用作 rest 参数的内容可以解析为 spread 运算符:
processData(data, ...results => {}) // Spread
processData(data, (...results) => {}) // Rest
赋值可能与默认参数混淆:
const a = 1;
let x;
const b = x => {}; // No default
const b = x = a => {}; // "Adding a default" instead creates a double assignment
const b = (x = a) => {}; // Remember to add parentheses
块看起来像对象:
(id) => id // Returns `id`
(id) => {name: id} // Returns `undefined` (it's a labeled statement)
(id) => ({name: id}) // Returns an object
这是什么意思?
() => {}
作者是否打算创建一个 no-op,或者一个返回空对象的函数?(考虑到这一点,我们是否应该在之后放置?我们是否应该将自己限制在表达式语法上?这将进一步降低箭头的频率。{
=>
=>
看起来像和:<=
>=
x => 1 ? 2 : 3
x <= 1 ? 2 : 3
if (x => 1) {}
if (x >= 1) {}
要立即调用箭头函数表达式,必须放在外面,但放在里面是有效的,可能是有意的。()
()
(() => doSomething()()) // Creates function calling value of `doSomething()`
(() => doSomething())() // Calls the arrow function
虽然,如果一个人写的目的是编写一个立即调用的函数表达式,那么什么都不会发生。(() => doSomething()());
考虑到上述所有情况,很难说箭头函数“更容易理解”。人们可以学习使用此语法所需的所有特殊规则。真的值得吗?
的语法是无可比拟的概括。独占使用意味着语言本身可以防止人们编写令人困惑的代码。要编写在所有情况下都应在语法上理解的过程,我选择 。function
function
function
关于指南
您要求制定一个需要“清晰”和“一致”的指南。使用箭头函数最终将导致语法上有效、逻辑上无效的代码,两种函数形式相互交织,有意义且任意。因此,我提供以下服务:
ES6 中的函数表示法指南:
- 始终使用 创建过程。
function
- 始终赋值给变量。请勿使用 。
this
() => {}