One of the most popular new features in ECMAScript 2015 is arrow functions. Is it because of the new cleaner syntax or the sharing of this with the parent scope? Maybe both. Let’s look into them in more detail.
箭头功能是ECMAScript 2015中最受欢迎的新功能之一。 是由于新的更干净的语法还是与父范围共享了此 语法 ? 也许两者都有。 让我们更详细地研究它们。
句法 (Syntax)
The first factor that influenced the introduction of arrow functions was a shorter function syntax. The syntax can look a bit different depending on the function. Let’s see some options!
影响箭头函数引入的第一个因素是较短的函数语法。 取决于功能,语法可能看起来有些不同。 让我们看看一些选择!
Here is a function written in ES5 syntax:
这是用ES5语法编写的函数:
var sum = function(a, b) {
return a + b;
}sum(1, 2) // -> 3
And here is the same function as an arrow function:
这是与箭头功能相同的功能:
const sum = (a, b) => a + b;sum(1, 2) // -> 3
As we can see the arrow function makes the code much more concise when we have one-line expressions. Due to implicit return we can omit the curly braces and return
keyword.
如我们所见,使用单行表达式时,箭头函数使代码更加简洁。 由于隐式返回,我们可以省略花括号和return
关键字。
If we have multiple lines in the function we always have to use the curly braces and return
:
如果函数中有多行,则总是必须使用花括号并return
:
const printSum = (a, b) => {
const sum = a + b;
console.log('Answer: ' + sum);
return sum;
}printSum(1, 2); // -> Answer: 3
Parentheses are optional when only one parameter is present:
仅存在一个参数时,括号是可选的:
const square = n => n * n;square(3); // -> 9
Arrow functions are sometimes called fat arrow functions, because of the token
=>
that resembles a fat arrow.箭头函数有时也称为胖箭头函数 ,因为类似于胖箭头的令牌
=>
。
A common use case for arrow functions is when using array methods. Here we create a new array with the ages of the players by mapping through the player array:
箭头函数的常见用例是使用数组方法时。 在这里,我们通过映射玩家数组来创建一个具有玩家年龄的新数组:
const players = [
{ name:’Michael’, age:44},
{ name:’Karl’, age:33},
{ name:’Lisa’, age:37}
];const ages = players.map(player => player.age); // [44, 33, 37]
Array functions really shine here!
数组函数真的在这里闪耀!
这个 (This)
We have seen how nice the new syntax can be but there is a another better reason to use arrow functions. And that is the sometimes confusing behavior of the this
keyword in JavaScript. It doesn’t depend on where it’s declared but on how and where the function is called, the execution context.
我们已经看到了新语法的效果,但是还有另一个更好的理由使用箭头函数。 这就是JavaScript中this
关键字有时令人困惑的行为。 它不依赖于声明的位置,而是依赖于调用函数的方式和位置( 执行上下文) 。
In the global scope, value of
this
is always thewindow
object.在全局范围内,
this
值始终是window
对象。
常规功能 (Regular Functions)
Functions have their own execution context and with it comes their own this
. Understanding these concepts is not easy but they are important.
函数具有自己的执行上下文,并且随之而来的是this
。 了解这些概念并不容易,但很重要。
Some example code can hopefully make it clearer. To show the difference we use setTimeout
, a native JavaScript function which calls a function after a set delay in milliseconds.
希望一些示例代码可以使它更清晰。 为了显示差异,我们使用setTimeout
,这是一个原生JavaScript函数,它会在设置的延迟(以毫秒为单位)后调用该函数。
// ES5
function Age() {
this.age = 42; setTimeout(function() {
console.log(this.age); // -> undefined
}, 1000);
}var a = new Age();
If we run this code we get undefined
logged to the console because the function inside setTimeout
has its own execution context. So we are not accessing this.age
of the Age
function but of the one inside the function where we make the call. And that hasn’t assigned a value to age
.
如果运行此代码,则setTimeout
的函数具有其自己的执行上下文,因此undefined
日志将记录到控制台。 因此,我们不访问Age
函数的this.age
,而是访问该函数中进行调用的那个Age
。 但这并没有给age
赋值。
To access the context of the parent function developers often reassign this
of the outer function to a variable commonly named that
or self
.
为了访问父函数的上下文,开发人员通常将外部函数的this
函数重新分配给一个通常称为that
或self
的变量。
// ES5
function Age() {
var that = this;
that.age = 42; setTimeout(function() {
console.log(that.age); // -> 42
}, 1000);
}var a = new Age();
In this way we can access the this
of the parent function but you can see how it can be confusing.
这样,我们可以访问父函数的this
,但是您可以看到它如何造成混淆。
Another option is to use
function{}.bind(this)
.另一种选择是使用
function{}.bind(this)
。
箭头功能 (Arrow Functions)
Arrow functions however share the lexical scope with their parent. This means that it uses this
from the code that contains the arrow function.
但是,箭头函数与其父级共享词法范围 。 这意味着,它使用this
从包含箭头函数的代码。
// ES6
function Age() {
this.age = 42; setTimeout(() => {
console.log(this.age); // -> 42
}, 1000);
}const a = new Age();
So, we can see how arrow functions help to make the code cleaner and easier to read.
因此,我们可以看到箭头功能如何帮助使代码更整洁,更易于阅读。
我们应该一直使用箭头功能吗? (Should we always use Arrow Functions?)
Arrow functions are great but there is still use for regular functions. Let’s see some examples when we should not use arrow functions.
箭头功能很棒,但仍用于常规功能。 让我们看一些不应使用箭头功能的示例。
方法 (Methods)
Arrow functions are best suited for non-method functions. Let’s see what happens when we try to use them as methods. In this example, we create an object blog
with a method like
.
箭头功能最适合非方法功能。 让我们看看当我们尝试将它们用作方法时会发生什么。 在这个例子中,我们创建一个对象blog
用的方法like
。
const blog = {
likes: 0,
like: () => {
this.likes++;
}
}
One would think that every time we call blog.like()
the attribute blog.likes
increases by one. However, sadly the value of likes will remain at zero.
有人会认为,每当我们将blog.like()
调用时, blog.like()
属性blog.likes
增加一。 但是,遗憾的是,点赞的价值将保持为零。
This time the parent scope is the window object and not the blog object. So invoking the method like()
would attempt to increment the property likes
on the window object.
这次,父作用域是窗口对象,而不是博客对象。 因此,调用like()
方法将尝试增加window对象上的likes
属性。
If instead, we use the traditional syntax it will work as expected:
相反,如果使用传统语法,它将按预期工作:
const blog = {
likes: 0,
like: function() {
this.likes++;
}
}
Even better, another new feature in ES6 is shorthand method syntax:
更好的是,ES6的另一个新功能是速记方法语法 :
const blog = {
likes: 0,
like() {
this.likes++;
}
}
建设者 (Constructor)
An arrow function cannot be used as a constructor. It will throw an error when used with new
:
箭头函数不能用作构造函数。 与new
使用时将抛出错误:
const PrintDouble = (x) => console.log(2 * x);new PrintDouble(2);// -> TypeError: PrintDouble is not a constructor
We can instead use a function expression:
我们可以改用函数表达式:
const PrintDouble = function(x) {
console.log(2 * x);
};new PrintDouble (2); // -> 4
结论 (Conclusion)
Array functions are a great new addition ES6 that brings us a syntactically compact alternative to a regular function. An arrow function does not have its own this. The this value of the enclosing lexical scope is used. Arrow functions are ill suited as methods, and they cannot be used as constructors.
数组函数是ES6的一项重要新增功能,它为我们带来了常规函数的语法紧凑的替代方案。 箭头函数没有它自己的函数。 使用封闭词法范围的this值。 箭头函数不适合用作方法,并且不能用作构造函数。
翻译自: https://medium.com/@michael.karen/getting-started-with-modern-javascript-arrow-functions-d38053b27e31