javascript ES6 箭头函数和使用 Function.prototype.bind 绑定的函数之间有什么区别(如果有)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32535110/
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
What are the differences (if any) between ES6 arrow functions and functions bound with Function.prototype.bind?
提问by Alexis King
It seems to me that, in ES6, the following two functions are very nearlyidentical:
在我看来,在 ES6 中,以下两个函数几乎相同:
function () {
return this;
}.bind(this);
() => {
return this;
};
The end result seems the same: arrow functions produce a JavaScript function object with their this
context bound to the same value as the this
where they are created.
最终结果似乎相同:箭头函数生成一个 JavaScript 函数对象,其this
上下文绑定到与this
创建它们的位置相同的值。
Obviously, in the general sense, Function.prototype.bind
is more flexible than arrow functions: it can bind to values other than the local this
, and it can bind any function's this
at any point in time, potentially long after it is initially created. However, I'm not asking how bind
itself is different from arrow functions, I'm asking how arrow functions differ from immediately calling bind
with this
.
显然,在一般意义上,Function.prototype.bind
它比箭头函数更灵活:它可以绑定到 local 以外的值this
,并且可以this
在任何时间点绑定任何函数,可能在最初创建之后很长时间。但是,我不是在问它bind
本身与箭头函数有何不同,我是在问箭头函数与立即调用bind
with 的不同之处this
。
Are there any differences between the two constructs in ES6?
ES6 中的两个构造之间有什么区别吗?
回答by Alexis King
There are no (significant) differences.
没有(显着)差异。
Well, okay, that's a little premature. There are three tinydifferences unique to arrow functions.
好吧,这有点为时过早。箭头函数有三个独特的细微差别。
Arrow functions cannot be used with
new
.This means, of course, that they do not have a
prototype
property and cannot be used to create an object with the classically-inspired syntax.new (() => {}) // TypeError: () => {} is not a constructor
This is probably for the best, though—the way
new
works would not make much sense with bound functions.Arrow functions do not have access to the special
arguments
object that ordinary JavaScript functions have access to.(() => arguments)(1, 2, 3) // ReferenceError: arguments is not defined
This one is probably a little bit more of a gotcha. Presumably this is to remove one of JavaScript's other oddities. The
arguments
object is its own special beast, and it has strange behavior, so it's not surprising that it was tossed.Instead, ES6 has splats that can accomplish the same thing without any magic hidden variables:
((...args) => args)(1, 2, 3) // [1, 2, 3]
Arrow functions do not have their own
new.target
property, they use thenew.target
of their enclosing function, if it exists.This is consistent with the other changes to remove "magically" introduced values for arrow functions. This particular change is especially obvious, considering arrow functions can't be used with
new
anyway, as mentioned above.
箭头函数不能与
new
.当然,这意味着它们没有
prototype
属性并且不能用于创建具有经典启发语法的对象。new (() => {}) // TypeError: () => {} is not a constructor
不过,这可能是最好的——这种工作方式
new
对绑定函数没有多大意义。箭头函数无法访问
arguments
普通 JavaScript 函数可以访问的特殊对象。(() => arguments)(1, 2, 3) // ReferenceError: arguments is not defined
这可能更像是一个陷阱。大概这是为了消除 JavaScript 的其他奇怪之处之一。该
arguments
物体是它自己的特殊野兽,它的行为很奇怪,所以它被扔掉也就不足为奇了。相反,ES6 有 splats 可以在没有任何神奇隐藏变量的情况下完成相同的事情:
((...args) => args)(1, 2, 3) // [1, 2, 3]
箭头函数没有自己的
new.target
属性new.target
,如果存在,它们会使用其封闭函数的 。这与删除箭头函数的“神奇”引入值的其他更改一致。这种特殊的变化特别明显,考虑到箭头函数
new
无论如何都不能使用,如上所述。
Otherwise, arrows are just like bound functions, semantically. It's possible for arrows to be more performant, since they don't have to carry around the extra baggage and since they don't need to be converted from ordinary functions first, but they're behaviorally exactly the same.
否则,在语义上,箭头就像绑定函数。箭头可能会更高效,因为它们不必携带额外的包袱,也不需要先从普通函数转换而来,但它们在行为上完全相同。
回答by Bergi
There are a few differences:
有一些区别:
Arrow functions cannot be constructed. While both arrow functions and bound functions both don't have a
.prototype
property, the former do throw an exception when called withnew
while the latter just ignore the bound value and call their target function as a constructor (with the partially applied bound arguments, though) on the new instance.function F() {} var f = () => {}, boundF = F.bind({}); console.log(new boundF(), new boundF instanceof F) // {}, true console.log(new f) // TypeError
Arrow functions do have lexical
arguments
,new.target
andsuper
as well (not only lexicalthis
). A call to an arrow function does not initialise any of those, they are just inherited from the function the arrow function was defined in. In a bound function, they just refer to the respective values of the target function.Arrow functions don't actually bind a
this
value. Rather, they don't have one, and when you usethis
it is looked up like a variable name in the lexical scope. This does allow you to lazily define an arrow function whilethis
is not yet available:class X extends Object { constructor() { var f = () => this, // works boundF = function(){ return this; }.bind(this); // ^^^^ ReferenceError super(); // initialises `this` console.log(f(), f() == this); // {}, true } } new X;
Arrow functions cannot be generator functions (though they can return generators). You can use
.bind()
on a generator function, yet there is no way to express this using an arrow function.
不能构造箭头函数。虽然箭头函数和绑定函数都没有
.prototype
属性,但前者在调用 withnew
时确实会抛出异常,而后者只是忽略绑定值并将其目标函数作为构造函数调用(尽管使用部分应用的绑定参数)在新实例上。function F() {} var f = () => {}, boundF = F.bind({}); console.log(new boundF(), new boundF instanceof F) // {}, true console.log(new f) // TypeError
箭头功能确实有词汇
arguments
,new.target
以及super
还有(不仅是词汇this
)。对箭头函数的调用不会初始化其中的任何一个,它们只是从定义箭头函数的函数继承而来。在绑定函数中,它们只引用目标函数的相应值。箭头函数实际上并不绑定一个
this
值。相反,它们没有,当您使用this
它时,它就像词法作用域中的变量名一样查找。这确实允许您在this
尚不可用时延迟定义箭头函数:class X extends Object { constructor() { var f = () => this, // works boundF = function(){ return this; }.bind(this); // ^^^^ ReferenceError super(); // initialises `this` console.log(f(), f() == this); // {}, true } } new X;
箭头函数不能是生成器函数(尽管它们可以返回生成器)。您可以
.bind()
在生成器函数上使用,但无法使用箭头函数来表达这一点。
回答by Chong Lip Phang
Here is one more subtle difference:
这是一个更细微的区别:
Arrow functions can return a value without using the 'return' keyword, by omitting the {} braces following the => immediately.
箭头函数可以在不使用 'return' 关键字的情况下返回一个值,方法是直接省略 => 后面的 {} 大括号。
var f=x=>x; console.log(f(3)); // 3
var g=x=>{x}; console.log(g(3)); // undefined
var h=function(x){x}; console.log(h(3)); // undefined
var i=x=>{a:1}; console.log(i(3)); // undefined
var j=x=>({a:1}); console.log(j(3)); // {a:1}