JavaScript 的箭头函数从表面上看可能与常规函数相同,但它们有一些非常重要的区别:
关键区别
- 语法
this
值(执行上下文)
- 用作类方法
- 用作构造函数
arguments
参数绑定
#. 语法
1
2
3
4
5
6
7
|
const square = a => a * a; // 允许省略单个参数周围的括号; 隐式返回;
// 等效常规function
function square(a) {
return a * a;
}
|
#. 执行上下文
1
2
3
4
5
6
7
8
9
10
11
12
13
|
const logThisArrow = () => {
console.log(this);
};
document.addEventListener('click', logThisArrow);
// `this` 指的是全局对象
// 常规函数
function logThis() {
console.log(this);
}
document.addEventListener('click', logThis);
// `this` 指的是 document
|
Function.prototype.call()
Function.prototype.bind()
Function.prototype.apply()
以上3个方法箭头函数也不能工作。因为这三个方法目的式允许函数在不同的范围内执行。
但是箭头函数的 this 值不能改变,因为它是词法解析的。
1
2
3
4
5
6
7
8
9
10
11
|
const logThisArrow = () => {
console.log(this);
};
logThisArrow.call(42); // Logs: 全局对象
// 常规函数
function logThis() {
console.log(this);
}
logThis.call(42); // Logs: 42
|
#. 用作类方法
由于箭头函数没有定义自己的执行上下文,因此它们不太适合用作方法。
然而,由于Class fields proposal
,如果您的环境支持,箭头函数可以用作类内部的方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
const obj = {
x: 42,
logThisX: function() {
console.log(this.x, this);
},
logThisXArrow: () => {
console.log(this.x, this);
}
};
obj.logThisX(); // Logs: 42, Object {...}
obj.logThisXArrow(); // Logs: undefined, the global object
|
#. 用作构造函数
常规函数可以用作构造函数,使用new
关键字。
this
内部箭头函数的词法解析的另一个结果是它们不能用作构造函数。使用new
在一个箭头作用的结果TypeError
。
1
2
3
4
5
6
7
8
9
10
|
const Bar = foo => {
this.foo = foo;
};
const b = new Bar(42); // TypeError: Bar is not a constructor
function Foo(bar) {
this.bar = bar;
}
const a = new Foo(42); // Foo {bar: 42}
|
#. arguments
参数绑定
另一个区别是arguments
对象的绑定。
与常规函数不同,箭头函数没有自己的arguments
对象。绕过此限制的现代替代方案是使用其余参数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
function sum() {
return arguments[0] + arguments[1];
};
sum(4, 6); // 10
const arguments = [1, 2, 3];
const sumArrow = () => {
return arguments[0] + arguments[1];
};
sumArrow(4, 6); // 3 (resolves to 1 + 2)
const sumRest = (...arguments) => {
return arguments[0] + arguments[1];
}
sumRest(4, 6); // 10
|
#. 其他差异
最后,还有一些其他差异并不那么重要,但值得一提。
这些包括缺少prototype
箭头函数中的属性,以及yield
关键字可能不会在箭头函数的主体中使用的事实。
后者的结果是箭头函数不能用作生成器。