Javascript “箭头函数”和“函数”等价/可交换吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34361379/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Are 'Arrow Functions' and 'Functions' equivalent / exchangeable?
提问by Felix Kling
Arrow functions in ES2015 provide a more concise syntax.
ES2015 中的箭头函数提供了更简洁的语法。
- Can I replace all my function declarations / expressions with arrow functions now?
- What do I have to look out for?
- 我现在可以用箭头函数替换我所有的函数声明/表达式吗?
- 我需要注意什么?
Examples:
例子:
Constructor function
构造函数
function User(name) {
this.name = name;
}
// vs
const User = name => {
this.name = name;
};
Prototype methods
原型方法
User.prototype.getName = function() {
return this.name;
};
// vs
User.prototype.getName = () => this.name;
Object (literal) methods
对象(文字)方法
const obj = {
getName: function() {
// ...
}
};
// vs
const obj = {
getName: () => {
// ...
}
};
Callbacks
回调
setTimeout(function() {
// ...
}, 500);
// vs
setTimeout(() => {
// ...
}, 500);
Variadic functions
可变函数
function sum() {
let args = [].slice.call(arguments);
// ...
}
// vs
const sum = (...args) => {
// ...
};
回答by Felix Kling
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 notuse this
, arguments
and is not called with new
, then yes.
tl;博士:不!箭头函数和函数声明/表达式不是等价的,不能盲目替换。
如果您要替换的函数不使用this
,arguments
并且未使用调用new
,则是。
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. 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 definedin (i.e. "outside" the arrow function):
箭头函数没有自己的this
或arguments
绑定的。相反,这些标识符像任何其他变量一样在词法范围内解析。这意味着,一个箭头函数内部,this
并且arguments
指的值this
和arguments
在箭头功能环境定义中(即,“外”的箭头功能):
// 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
. In the arrow function case, this
refers to this
of createObject
itself.
在函数表达式的情况下,this
指的是在createObject
. 在箭头函数的情况下,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;
});
Notethat this also means that is notpossible 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 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).
ES2015 区分了可调用函数和可构造函数。如果函数是可构造的,则可以使用 调用它 new
,即new User()
。如果一个函数是可调用的,它就可以在没有调用的情况下被调用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
orarguments
. - Functions that are used with
.bind(this)
- 不使用
this
or 的函数arguments
。 - 使用的函数
.bind(this)
Notreplaceable:
不可更换:
- Constructor functions
- Function / methods added to a prototype (because they usually use
this
) - Variadic functions (if they use
arguments
(see below))
- 构造函数
- 添加到原型的函数/方法(因为它们通常使用
this
) - 可变参数函数(如果它们使用
arguments
(见下文))
Lets have a closer look at this using your examples:
让我们用你的例子仔细看看这个:
Constructor function
构造函数
This won't work because arrow functions cannot be called with new
. Keep using a function declaration / expression or use class
.
这是行不通的,因为箭头函数不能用new
. 继续使用函数声明/表达式或使用class
.
Prototype methods
原型方法
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:
很可能不是,因为原型方法通常用于this
访问实例。如果他们不使用this
,那么您可以更换它。但是,如果您主要关心简洁的语法,请使用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 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 cannotuse 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. However, ES2015 introduces an alternative to using arguments
: the rest parameter.
由于箭头函数没有自己的arguments
,您不能简单地用箭头函数替换它们。但是,ES2015 引入了使用的替代方法arguments
:rest 参数。
// old
function sum() {
let args = [].slice.call(arguments);
// ...
}
// new
const sum = (...args) => {
// ...
};
Related question:
相关问题:
- 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?
- 什么时候应该在 ECMAScript 6 中使用箭头函数?
- ES6 箭头函数是否有自己的参数?
- ES6 箭头函数和使用 Function.prototype.bind 绑定的函数之间有什么区别(如果有)?
- 如何使用箭头函数(公共类字段)作为类方法?
Further resources:
更多资源:
回答by Ashutosh
Arrow functions => best ES6 feature so far. They are a tremendously powerful addition to ES6, that I use constantly.
箭头函数 => 迄今为止最好的 ES6 特性。它们是 ES6 的一个非常强大的补充,我经常使用。
Wait, you can't use arrow function everywhere in your code, its not going to work in all cases like this
where arrow functions are not usable. Without a doubt, the arrow function is a great addition it brings code simplicity.
等等,你不能在你的代码中到处使用箭头函数,它不会在所有情况下都起作用,比如this
箭头函数不可用的地方。毫无疑问,箭头函数是一个很好的补充,它带来了代码的简单性。
But you can't use an arrow function when a dynamic context is required: defining methods, create objects with constructors, get the target from this when handling events.
但是当需要动态上下文时不能使用箭头函数:定义方法,使用构造函数创建对象,在处理事件时从中获取目标。
Arrow functions should NOT be used because:
不应使用箭头函数,因为:
They do not have
this
It uses “lexical scoping” to figure out what the value of “
this
” should be. In simple word lexical scoping it uses “this
” from the inside the function's body.They do not have
arguments
Arrow functions don't have an
arguments
object. But the same functionality can be achieved using rest parameters.let sum = (...args) => args.reduce((x, y) => x + y, 0)
sum(3, 3, 1) // output - 7
`They cannot be used with
new
Arrow functions can't be construtors because they do not have a prototype property.
他们没有
this
它使用“词法范围”来确定“ ”的值
this
应该是什么。在简单的词法作用域中,它使用this
函数体内的“ ”。他们没有
arguments
箭头函数没有
arguments
对象。但是使用其余参数可以实现相同的功能。let sum = (...args) => args.reduce((x, y) => x + y, 0)
sum(3, 3, 1) // output - 7
`它们不能与
new
箭头函数不能是构造函数,因为它们没有原型属性。
When to use arrow function and when not:
何时使用箭头函数,何时不使用:
- Don't use to add function as a property in object literal because we can not access this.
- Function expressions are best for object methods. Arrow functions
are best for callbacks or methods like
map
,reduce
, orforEach
. - Use function declarations for functions you'd call by name (because they're hoisted).
- Use arrow functions for callbacks (because they tend to be terser).
- 不要使用将函数作为属性添加到对象字面量中,因为我们无法访问它。
- 函数表达式最适合对象方法。箭头函数最适合回调或方法,如
map
、reduce
、 或forEach
。 - 对按名称调用的函数使用函数声明(因为它们被提升)。
- 对回调使用箭头函数(因为它们往往更简洁)。
回答by toddmo
To use arrow functions with function.prototype.call
, I made a helper function on the object prototype:
为了使用箭头函数function.prototype.call
,我在对象原型上创建了一个辅助函数:
// Using
// @func = function() {use this here} or This => {use This here}
using(func) {
return func.call(this, this);
}
usage
用法
var obj = {f:3, a:2}
.using(This => This.f + This.a) // 5
Edit
编辑
You don't NEED a helper. You could do:
你不需要帮手。你可以这样做:
var obj = {f:3, a:2}
(This => This.f + This.a).call(undefined, obj); // 5