ES6深入:箭头功能
这是一篇关于ECMAScript标准第6版(简称ES6)中添加到JavaScript编程语言的新功能的系列文章
箭头从一开始就是JavaScript的一部分。第一个JavaScript教程建议在HTML注释中包装内联脚本。这样可以防止不支持JS的浏览器错误地将JS代码显示为文本。
<script language="javascript">
<!--
document.bgColor = "brown"; // red
// -->
</script>
旧浏览器会看到两个不受支持的标签和标注; 只有新的浏览器会看到JS代码。
这种评论风格在ES6中首次实现了标准化。但这不是我们在这里谈论的箭头。
箭头序列-->也表示单行注释。奇怪,而在HTML字符前的-->是注释的一部分,在JS行的其余部分之后的-->是注释。
它变得陌生。此箭头仅在出现在行首时显示注释。那是因为在其他情况下,-->JS中的运算符是“转到”运算符!
function countdown(n) {
while (n --> 0) // "n goes to zero"
alert(n);
blastoff();
}
这段代码确实有效。循环运行,直到ň到达0。这也是没有在ES6的一项新功能,但熟悉的功能组合,向其中投入了一点误导。你能弄清楚是怎么回事?像往常一样,拼图的答案可以在Stack Overflow上找到。
函数表达式无处不在
JavaScript的一个有趣功能是,只要您需要一个函数,就可以在运行代码的过程中直接输入该函数。
例如,假设您试图告诉浏览器在用户单击特定按钮时要执行的操作。你开始输入:
$("#confetti-btn").click()
jQuery的.click()方法有一个参数:一个函数。没问题。你可以在这里输入一个函数:
$("#confetti-btn").click(function (event) {
playTrumpet();
fireConfettiCannon();
});
像这样编写代码对我们来说非常自然。所以很奇怪回忆一下,在JavaScript推广这种编程之前,许多语言都没有这个功能。当然,Lisp 在1958年有函数表达式,也称为lambda函数。但是C ++,Python,C#和Java都存在多年而没有它们。
不再。现在这四个人都有lambdas。较新的语言通常都内置了lambdas。我们有JavaScript来感谢这个以及早期的JavaScript程序员,他们无畏地构建了严重依赖lambda的库,从而导致了该功能的广泛采用。
然而,在我提到的所有语言中,有点令人遗憾的是,lambd的JavaScript语法已经证明是最有效的。
// A very simple function in six languages.
function (a) { return a > 0; } // JS
[](int a) { return a > 0; } // C++
(lambda (a) (> a 0)) ;; Lisp
lambda a: a > 0 # Python
a => a > 0 // C#
a -> a > 0 // Java
箭袋中的新箭头
ES6引入了一种用于编写函数的新语法。
// ES5
var selected = allJobs.filter(function (job) {
return job.isSelected();
});
// ES6
var selected = allJobs.filter(job => job.isSelected());
当你只需要一个带有一个参数的简单函数时,新的箭头函数语法很简单。你跳过打字和,以及一些括号,括号和一个分号。Identifier => Expressionfunctionreturn
(我个人非常感谢这个功能。不必输入function对我来说很重要,因为我不可避免地要输入functoin并且必须返回并纠正它。)
要编写具有多个参数(或没有参数,休息参数或默认值或解构参数)的函数,您需要在参数列表周围添加括号。
// ES5
var total = values.reduce(function (a, b) {
return a + b;
}, 0);
// ES6
var total = values.reduce((a, b) => a + b, 0);
我觉得它看起来很不错。
Arrow函数与库提供的功能工具(如Underscore.js和Immutable)一样工作得非常漂亮。实际上,Immutable文档中的示例都是用ES6编写的,因此很多都使用了箭头函数。
不那么功能的设置怎么样?箭头函数可以包含一个语句块而不仅仅是一个表达式。回想一下我们之前的例子:
// ES5
$("#confetti-btn").click(function (event) {
playTrumpet();
fireConfettiCannon();
});
以下是它在ES6中的外观:
// ES6
$("#confetti-btn").click(event => {
playTrumpet();
fireConfettiCannon();
});
一个小小的改进。使用Promise对代码的影响可能会更加引人注目,因为}).then(function (result) {线条会堆积起来。
请注意,带有块体的箭头函数不会自动返回值。请使用return声明。
使用箭头函数创建普通对象时有一点需要注意。始终将对象括在括号中:
// create a new empty object for each puppy to play with
var chewToys = puppies.map(puppy => {}); // BUG!
var chewToys = puppies.map(puppy => ({})); // ok
不幸的是,空对象{}和空块{}看起来完全一样。ES6中的规则是{紧跟在箭头后面始终被视为块的开始,而不是对象的开始。puppy => {}因此,代码被静默地解释为箭头函数,它不执行任何操作并返回undefined。
更令人困惑的是,对象字面{key: value}看起来就像一个包含带标签语句的块 - 至少,这就是它对你的JavaScript引擎的看法。幸运的{是,这是唯一不明确的角色,所以在括号中包装对象文字是你需要记住的唯一技巧。
普通function函数和箭头函数之间的行为有一个细微的差别。箭头函数没有自己的this值。this箭头函数内部的值始终从封闭范围继承。
在我们尝试找出实际意义之前,让我们先回顾一下。
如何this在JavaScript 中工作?它的价值来自哪里?没有简短的回答。如果它看起来很简单,那是因为你已经和它打了很长时间了!
这个问题经常出现的一个原因是function函数会this自动接收一个值,无论他们是否想要一个值。你有没有写过这个黑客?
{
...
addAll: function addAll(pieces) {
var self = this;
_.each(pieces, function (piece) {
self.add(piece);
});
},
...
}
在这里,你会喜欢在内部函数写就是this.add(piece)。不幸的是,内部函数不继承外部函数的this值。在内部功能内部,this将是window或undefined。临时变量self用于将外部值走私this到内部函数中。(另一种方法是使用.bind(this)内部函数。两种方式都不是特别漂亮。)
在ES6中,this如果遵循以下规则,黑客大多会消失:
对于将使用object.method()语法调用的方法,请使用非箭头函数。这些函数将从调用者那里获得有意义的 this值。
将箭头功能用于其他一切。
// ES6
{
...
addAll: function addAll(pieces) {
_.each(pieces, piece => this.add(piece));
},
...
}
在ES6版本中,请注意该addAll方法this从其调用方接收。内部函数是一个箭头函数,因此它继承this了封闭范围。
作为奖励,ES6还提供了一种在对象文字中编写方法的简短方法!所以上面的代码可以进一步简化:
// ES6 with method syntax
{
...
addAll(pieces) {
_.each(pieces, piece => this.add(piece));
},
...
}
在方法和箭头之间,我可能永远不会再打字functoin。这是一个很好的想法。
箭头和非箭头函数之间还有一个小的区别:箭头函数也没有自己的arguments对象。当然,在ES6中,你可能宁愿使用rest参数或默认值。
-
Prev通过标签方式引入antd时date-picker报错:"TypeError: Cannot read property 'default' of undefined"
-
NextJavaScript:箭头函数