“箭头功能”和“功能”是否等效/可互换? [英] Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
问题描述
ES2015中的箭头功能提供了更简洁的语法。
Arrow functions in ES2015 provide a more concise syntax.
- 我现在可以用箭头函数替换所有函数声明/表达式吗?
- 我要寻找什么?
示例:
构造函数
function User(name) {
this.name = name;
}
// vs
const User = name => {
this.name = name;
};
原型方法
User.prototype.getName = function() {
return this.name;
};
// vs
User.prototype.getName = () => this.name;
对象(文字)方法
const obj = {
getName: function() {
// ...
}
};
// vs
const obj = {
getName: () => {
// ...
}
};
回调
setTimeout(function() {
// ...
}, 500);
// vs
setTimeout(() => {
// ...
}, 500);
可变函数
function sum() {
let args = [].slice.call(arguments);
// ...
}
// vs
const sum = (...args) => {
// ...
};
推荐答案
tl; dr: 否!箭头函数和函数声明/表达式不等效,不能盲目替换。
如果要替换的函数不使用 not 此
,参数
,并且不使用 new
进行调用,然后是的。
tl;dr: No! Arrow functions and function declarations / expressions are not equivalent and cannot be replaced blindly.
If the function you want to replace does not use this
, arguments
and is not called with new
, then yes.
通常:这取决于。箭头函数的行为不同于函数声明/表达式的行为,因此让我们首先看一下它们之间的区别:
As so often: it depends. Arrow functions have different behavior than function declarations / expressions, so let's have a look at the differences first:
1。词法 this
和 arguments
1. Lexical this
and arguments
箭头函数不有自己的 this
或 arguments
绑定。相反,这些标识符像任何其他变量一样在词法范围内解析。这意味着在箭头函数中, this
和 arguments
引用 this
和 arguments
的环境中,箭头功能是在定义中定义的(即外部箭头功能):
Arrow functions don't have their own this
or arguments
binding. Instead, those identifiers are resolved in the lexical scope like any other variable. That means that inside an arrow function, this
and arguments
refer to the values of this
and arguments
in the environment the arrow function is defined in (i.e. "outside" the arrow function):
// Example using a function expression
function createObject() {
console.log('Inside `createObject`:', this.foo);
return {
foo: 42,
bar: function() {
console.log('Inside `bar`:', this.foo);
},
};
}
createObject.call({foo: 21}).bar(); // override `this` inside createObject
// Example using a arrow function
function createObject() {
console.log('Inside `createObject`:', this.foo);
return {
foo: 42,
bar: () => console.log('Inside `bar`:', this.foo),
};
}
createObject.call({foo: 21}).bar(); // override `this` inside createObject
在函数表达式中, this
表示在 createObject
内部创建的对象。在箭头函数情况下, this
表示 createObject
this
In the function expression case, this
refers to the object that was created inside the createObject
. In the arrow function case, this
refers to this
of createObject
itself.
如果需要访问当前环境的 this
,这会使箭头功能有用:
This makes arrow functions useful if you need to access the this
of the current environment:
// currently common pattern
var that = this;
getData(function(data) {
that.data = data;
});
// better alternative with arrow functions
getData(data => {
this.data = data;
});
注意,这也意味着不能设置箭头函数的 this
与 .bind
或 .call
。
Note that this also means that is not possible to set an arrow function's this
with .bind
or .call
.
如果您不太熟悉此
,请考虑阅读
If you are not very familiar with this
, consider reading
- MDN - this
- YDKJS - this & Object prototypes
2。无法使用 new
2. Arrow functions cannot be called with new
ES2015区分可调用 的函数和可以构造的功能。如果函数是可构造的,则可以使用 new
调用,即 new User()
。如果一个函数是可调用的,则可以在不使用 new
(即正常函数调用)的情况下对其进行调用。
ES2015 distinguishes between functions that are callable and functions that are constructable. If a function is constructable, it can be called with new
, i.e. new User()
. If a function is callable, it can be called without new
(i.e. normal function call).
通过函数声明/表达式创建的函数既可构造又可调用。
箭头函数(和方法)仅可调用。
类
构造函数只能构造。
Functions created through function declarations / expressions are both constructable and callable.
Arrow functions (and methods) are only callable.
class
constructors are only constructable.
如果您试图调用不可调用的函数或构造一个不可调用的函数可构造函数,您会遇到运行时错误。
If you are trying to call a non-callable function or to construct a non-constructable function, you will get a runtime error.
知道这一点后,我们可以陈述以下内容。
Knowing this, we can state the following.
可替换:
- 不使用
this
或参数的函数
。 - 与
.bind(this)
- Functions that don't use
this
orarguments
. - Functions that are used with
.bind(this)
不可可替换:
- 构造函数
- 添加到原型的函数/方法(因为它们通常使用
this
) - 可变参数函数(如果它们使用
参数
(见下文))
- Constructor functions
- Function / methods added to a prototype (because they usually use
this
) - Variadic functions (if they use
arguments
(see below))
让我们用您的例子仔细研究一下:
Lets have a closer look at this using your examples:
构造函数
这是行不通的,因为箭头函数不能用调用新
。继续使用函数声明/表达式或使用 class
。
This won't work because arrow functions cannot be called with new
. Keep using a function declaration / expression or use class
.
原型方法
很有可能不会,因为原型方法通常使用 this
来访问实例。如果他们不使用 this
,则可以将其替换。但是,如果您主要关心简洁的语法,请使用 class
及其简洁的方法语法:
Most likely not, because prototype methods usually use this
to access the instance. If they don't use this
, then you can replace it. However, if you primarily care for concise syntax, use class
with its concise method syntax:
class User {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
对象方法
与对象文字中的方法类似。如果方法想通过 this
引用对象本身,请继续使用函数表达式或使用新的方法语法:
Similarly for methods in an object literal. If the method wants to reference the object itself via this
, keep using function expressions, or use the new method syntax:
const obj = {
getName() {
// ...
},
};
回调
这取决于。如果要别名外部 this
或使用 .bind(this)
:
It depends. You should definitely replace it if you are aliasing the outer this
or are using .bind(this)
:
// old
setTimeout(function() {
// ...
}.bind(this), 500);
// new
setTimeout(() => {
// ...
}, 500);
但是:如果调用回调的代码明确设置了 this
设置为特定值,事件处理程序(尤其是jQuery)通常如此,并且回调使用 this
(或参数
),则不能使用箭头功能!
But: If the code which calls the callback explicitly sets this
to a specific value, as is often the case with event handlers, especially with jQuery, and the callback uses this
(or arguments
), you cannot use an arrow function!
可变参数函数
由于箭头函数没有自己的自变量
,因此不能简单地将它们替换为箭头函数。但是,ES2015引入了使用 arguments
的替代方法:休息参数。
Since arrow functions don't have their own arguments
, you cannot simply replace them with an arrow function. However, ES2015 introduces an alternative to using arguments
: the rest parameter.
// old
function sum() {
let args = [].slice.call(arguments);
// ...
}
// new
const sum = (...args) => {
// ...
};
相关问题:
Related question:
- 何时应在ECMAScript 6中使用Arrow函数?
- < a href = https://stackoverflow.com/q/33288998/1048572> ES6箭头函数是否有其自变量?
- ES6箭头函数与与Function.prototype.bind绑定的函数之间有什么区别(如果有)?
- 如何将箭头函数(公共类字段)用作类方法?
- When should I use Arrow functions in ECMAScript 6?
- Do ES6 arrow functions have their own arguments or not?
- What are the differences (if any) between ES6 arrow functions and functions bound with Function.prototype.bind?
- How to use arrow functions (public class fields) as class methods?
其他资源:
- MDN - Arrow functions
- YDKJS - Arrow functions
这篇关于“箭头功能”和“功能”是否等效/可互换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!