tl;dr: No!
(tl; dr: 不!)
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.(如果您要替换的函数未使用this
, arguments
并且未使用new
arguments
,则为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. Lexical this
and arguments
(1.词汇this
和arguments
)
Arrow functions don't have their own this
or arguments
binding.
(箭头函数没有自己的this
或arguments
绑定。)
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 (ie "outside" the arrow function):(这意味着在arrow函数中, this
和arguments
指的是定义 arrow函数的环境中的this
和arguments
的值(即arrow函数的“外部”):)
// 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
In the function expression case, this
refers to the object that was created inside the createObject
.
(在函数表达式的情况下, this
是指在createObject
内部创建的对象。)
In the arrow function case, this
refers to this
of createObject
itself.(在箭头功能的情况下, this
指的是this
的createObject
本身。)
This makes arrow functions useful if you need to access the this
of the current environment:
(如果需要访问当前环境的this
,这将使箭头功能有用:)
// currently common pattern
var that = this;
getData(function(data) {
that.data = data;
});
// better alternative with arrow functions
getData(data => {
this.data = data;
});
Note that this also means that is not possible to set an arrow function's this
with .bind
or .call
.
(请注意 ,这也意味着这是不可能的设置箭头的功能是this
用.bind
或.call
。)
If you are not very familiar with this
, consider reading
(如果你不是很熟悉this
,可以阅读)
2. Arrow functions cannot be called with new
(2.箭头函数不能用new
调用)
ES2015 distinguishes between functions that are call able and functions that are construct able.
(ES2015区分了可调用的功能和可构造的功能。)
If a function is constructable, it can be called with new
, ie new User()
.(如果一个函数是可构造的,则可以使用new
,即new User()
来调用它。)
If a function is callable, it can be called without new
(ie normal function call).(如果一个函数是可调用的,则可以在不使用new
函数的情况下对其进行调用(即正常的函数调用)。)
Functions created through function declarations / expressions are both constructable and callable.
(通过函数声明/表达式创建的函数是可构造的和可调用的。)
Arrow functions (and methods) are only callable.(箭头函数(和方法)只能调用。)
class
constructors are only constructable.(class
构造函数只能构造。)
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.
(知道了这一点,我们可以陈述以下内容。)
Replaceable:
(可更换的:)
- Functions that don't use
this
or arguments
.(不使用this
或arguments
。)
- Functions that are used with
.bind(this)
(与.bind(this)
一起使用的函数)
Not replaceable:
(不可更换:)
Lets have a closer look at this using your examples:
(让我们使用您的示例仔细看一下:)
Constructor function
(构造函数)
This won't work because arrow functions cannot be called with new
.
(这将无法正常工作,因为无法使用new
调用箭头函数。)
Keep using a function declaration / expression or use class
.(继续使用函数声明/表达式或使用class
。)
Prototype methods
(原型方法)
Most likely not, because prototype methods usually use this
to access the instance.
(很有可能不是,因为原型方法通常使用this
来访问实例。)
If they don't use this
, then you can replace it.(如果他们不使用this
,那么你就可以取代它。)
However, if you primarily care for concise syntax, use class
with its concise method syntax:(但是,如果您主要关心简洁的语法,请使用class
及其简洁的方法语法:)
class User {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
Object methods
(对象方法)
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:(如果方法要通过this
引用对象本身,请继续使用函数表达式,或使用新的方法语法:)
const obj = {
getName() {
// ...
},
};
Callbacks
(回呼)
It depends.
(这取决于。)
You should definitely replace it if you you are aliasing the outer this
or are using .bind(this)
:(如果您要别名外部this
或使用.bind(this)
,则绝对应该替换它:)
// old
setTimeout(function() {
// ...
}.bind(this), 500);
// new
setTimeout(() => {
// ...
}, 500);
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!
(但是:如果调用回调的代码将事件显式地this
值设置为特定值(在事件处理程序中,尤其是在jQuery中),并且回调使用this
(或arguments
), 则不能使用箭头函数!)
Variadic functions
(可变函数)
Since arrow functions don't have their own arguments
, you cannot simply replace them with an arrow function.
(由于箭头函数没有自己的arguments
,因此不能简单地将其替换为箭头函数。)
However, ES2015 introduces an alternative to using arguments
: the rest parameter .(但是,ES2015引入了使用arguments
的替代方法: rest参数 。)
// old
function sum() {
let args = [].slice.call(arguments);
// ...
}
// new
const sum = (...args) => {
// ...
};
Related question:
(相关问题:)