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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 15:26:07  来源:igfitidea点击:

What are the differences (if any) between ES6 arrow functions and functions bound with Function.prototype.bind?

javascriptecmascript-6arrow-functionsfunction-binding

提问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 thiscontext bound to the same value as the thiswhere they are created.

最终结果似乎相同:箭头函数生成一个 JavaScript 函数对象,其this上下文绑定到与this创建它们的位置相同的值。

Obviously, in the general sense, Function.prototype.bindis more flexible than arrow functions: it can bind to values other than the local this, and it can bind any function's thisat any point in time, potentially long after it is initially created. However, I'm not asking how binditself is different from arrow functions, I'm asking how arrow functions differ from immediately calling bindwith this.

显然,在一般意义上,Function.prototype.bind它比箭头函数更灵活:它可以绑定到 local 以外的值this,并且可以this在任何时间点绑定任何函数,可能在最初创建之后很长时间。但是,我不是在问它bind本身与箭头函数有何不同,我是在问箭头函数与立即调用bindwith 的不同之处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.

好吧,这有点为时过早。箭头函数有三个独特的细微差别。

  1. Arrow functions cannot be used with new.

    This means, of course, that they do not have a prototypeproperty 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 newworks would not make much sense with bound functions.

  2. Arrow functions do not have access to the special argumentsobject 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 argumentsobject 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]
    
  3. Arrow functions do not have their own new.targetproperty, they use the new.targetof 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 newanyway, as mentioned above.

  1. 箭头函数不能与new.

    当然,这意味着它们没有prototype属性并且不能用于创建具有经典启发语法的对象。

    new (() => {}) // TypeError: () => {} is not a constructor
    

    不过,这可能是最好的——这种工作方式new对绑定函数没有多大意义。

  2. 箭头函数无法访问arguments普通 JavaScript 函数可以访问的特殊对象。

    (() => arguments)(1, 2, 3) // ReferenceError: arguments is not defined
    

    这可能更像是一个陷阱。大概这是为了消除 JavaScript 的其他奇怪之处之一。arguments物体是它自己的特殊野兽,它的行为很奇怪,所以它被扔掉也就不足为奇了。

    相反,ES6 有 splats 可以在没有任何神奇隐藏变量的情况下完成相同的事情:

    ((...args) => args)(1, 2, 3) // [1, 2, 3]
    
  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 .prototypeproperty, the former do throw an exception when called with newwhile 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.targetand superas well (not only lexical this). 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 thisvalue. Rather, they don't have one, and when you use thisit is looked up like a variable name in the lexical scope. This does allow you to lazily define an arrow function while thisis 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
    
  • 箭头功能确实有词汇argumentsnew.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}