Javascript ES6 arrow函数和使用Function.prototype.bind绑定的函数之间有什么区别(如果有)?
在我看来,在ES6中,以下两个功能几乎相同:Javascript ES6 arrow函数和使用Function.prototype.bind绑定的函数之间有什么区别(如果有)?,javascript,ecmascript-6,arrow-functions,function-binding,Javascript,Ecmascript 6,Arrow Functions,Function Binding,在我看来,在ES6中,以下两个功能几乎相同: function () { return this; }.bind(this); () => { return this; }; 最终结果似乎是一样的:箭头函数生成一个JavaScript函数对象,其this上下文绑定到与创建它们的this相同的值 显然,在一般意义上,Function.prototype.bind比箭头函数更灵活:它可以绑定到本地this以外的值,并且它可以在任何时间点绑定任何函数的this,可能在最初创建之后很长
function () {
return this;
}.bind(this);
() => {
return this;
};
最终结果似乎是一样的:箭头函数生成一个JavaScript函数对象,其this
上下文绑定到与创建它们的this
相同的值
显然,在一般意义上,Function.prototype.bind
比箭头函数更灵活:它可以绑定到本地this
以外的值,并且它可以在任何时间点绑定任何函数的this
,可能在最初创建之后很长时间。但是,我不是问bind
本身与arrow函数有什么不同,我是问arrow函数与使用this
立即调用bind
有什么不同
ES6中的两种结构之间是否存在任何差异?没有(显著)差异。
好吧,这有点过早。箭头函数有三个独特的细微差别
new
一起使用
当然,这意味着它们没有prototype
属性,不能用于创建具有经典语法的对象
new (() => {}) // TypeError: () => {} is not a constructor
这可能是最好的,尽管new
的工作方式对于绑定函数没有多大意义参数
对象
(() => arguments)(1, 2, 3) // ReferenceError: arguments is not defined
这一个可能是一个多一点的陷阱。这大概是为了消除JavaScript的另一个奇怪之处,而且它有奇怪的行为,所以它被扔也就不足为奇了
相反,ES6的SPlat可以在没有任何神奇隐藏变量的情况下完成相同的任务:
((...args) => args)(1, 2, 3) // [1, 2, 3]
new.target
(如果存在)
这与删除箭头函数“神奇”引入值的其他更改是一致的。考虑到箭头函数无论如何不能与new
一起使用,如上所述,这种特殊的变化尤其明显否则,箭头在语义上就像绑定函数一样。箭头的性能可能更高,因为它们不需要携带额外的行李,也不需要首先从普通功能转换而来,但它们的行为完全相同。有一些区别:
- 无法构造箭头函数。虽然箭头函数和绑定函数都没有
属性,但前者在使用.prototype
调用时会引发异常,而后者只是忽略绑定值,并将其目标函数作为新实例上的构造函数调用(尽管部分应用了绑定参数)new
function F() {} var f = () => {}, boundF = F.bind({}); console.log(new boundF(), new boundF instanceof F) // {}, true console.log(new f) // TypeError
- 箭头函数也有词法
,参数
和新.目标
(不仅仅是词法超级
)。对arrow函数的调用不会初始化这些函数中的任何一个,它们只是从定义arrow函数的函数继承而来。在绑定函数中,它们只引用目标函数的相应值这个
- 箭头函数实际上并不绑定
这个
值。相反,它们没有一个,当您使用
时,它在词法范围内就像一个变量名一样查找。这允许您在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()
- 这里还有一个微妙的区别:
箭头函数可以通过立即省略=>后面的{}大括号而不使用'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}
使用
bind
基本上可以创建两个函数。除此之外,你提到的事情和箭头函数有更简洁的语法这一事实没有区别。因为这个问题不寻求答案,而且它的答案也没有提供任何时候你有充分的理由在箭头函数上使用bind
,我问了一个关于何时执行此操作的新问题:在bind
版本中,它返回一个新函数,该函数将部分参数应用于bind
。Arrow没有这个
,所以它是作为更高范围内的任何自由变量使用的。我不会说参数
被抛出是因为“奇怪的行为”(这在严格模式下是固定的)。相反,arrow函数可以访问其封闭函数的参数
对象,这与它们访问其此
绑定和新建的方式一致。target
@Bergi即使在严格模式下,参数
也相当奇怪:它仍然不是数组,因此splat仍然更有用和可预测。@AlexisKing,在你的回答中,你应该明确提到接受父母的背景。我认为这不是一个特别有用的答案。是的-大括号可以省略-这很方便,但这只是语法上的差异,而不是功能上的差异。我认为这是一个很好的答案,特别是如果你不懂所有的速记语法