让我们重新审视箭头函数。
箭头函数不仅仅是编写小内容的“速记”。它们有一些非常具体且有用的功能。
JavaScript 中充斥着我们需要编写一个在其他地方执行的小函数的情况。
例如
arr.forEach(func)
–func
由forEach
为每个数组项执行。setTimeout(func)
–func
由内置调度程序执行。- …还有更多。
创建函数并将其传递到某个地方是 JavaScript 的精髓所在。
在这些函数中,我们通常不想离开当前上下文。这就是箭头函数派上用场的地方。
箭头函数没有“this”
正如我们从章节对象方法,“this”中了解到的,箭头函数没有this
。如果访问this
,它将从外部获取。
例如,我们可以在对象方法中使用它进行迭代
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(
student => alert(this.title + ': ' + student)
);
}
};
group.showList();
这里在forEach
中使用了箭头函数,因此其中的this.title
与外部方法showList
中的完全相同。即:group.title
。
如果我们使用“常规”函数,则会出现错误
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(function(student) {
// Error: Cannot read property 'title' of undefined
alert(this.title + ': ' + student);
});
}
};
group.showList();
出现错误是因为forEach
默认使用this=undefined
运行函数,因此尝试访问undefined.title
。
这不会影响箭头函数,因为它们根本没有this
。
箭头函数不能用
new
运行没有this
自然意味着另一个限制:箭头函数不能用作构造函数。它们不能用new
调用。
箭头函数与 bind
箭头函数=>
和用.bind(this)
调用的常规函数之间存在细微差别
.bind(this)
创建函数的“绑定版本”。- 箭头
=>
不会创建任何绑定。该函数根本没有this
。this
的查找方式与常规变量搜索完全相同:在外部词法环境中。
箭头没有“参数”
箭头函数也没有arguments
变量。
当我们需要使用当前this
和arguments
转发调用时,这对于装饰器来说非常棒。
例如,defer(f, ms)
获取一个函数并返回一个包装器,该包装器将调用延迟ms
毫秒
function defer(f, ms) {
return function() {
setTimeout(() => f.apply(this, arguments), ms);
};
}
function sayHi(who) {
alert('Hello, ' + who);
}
let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("John"); // Hello, John after 2 seconds
没有箭头函数的相同内容如下所示
function defer(f, ms) {
return function(...args) {
let ctx = this;
setTimeout(function() {
return f.apply(ctx, args);
}, ms);
};
}
在这里,我们必须创建附加变量args
和ctx
,以便setTimeout
中的函数可以获取它们。
总结
箭头函数
- 没有
this
- 没有
arguments
- 不能用
new
调用 - 它们也没有
super
,但我们还没有学习它。我们将在章节类继承中学习它
这是因为它们适用于没有自己“上下文”的短代码片段,而是在当前上下文中工作。并且它们在这种用例中确实很出色。
评论
<code>
标记,对于多行代码 – 将其包装在<pre>
标记中,对于 10 行以上的代码 – 使用沙盒(plnkr、jsbin、codepen…)