54

在我看来,在 ES6 中,以下两个函数几乎完全相同

function () {
  return this;
}.bind(this);

() => {
  return this;
};

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

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

ES6 中的这两种结构有什么不同吗?

4

3 回答 3

38

没有(显着)差异。

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

  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如上所述,考虑到箭头函数无论如何都不能使用,这种特殊的变化尤其明显。

否则,箭头在语义上就像绑定函数。箭头可能具有更高的性能,因为它们不必携带额外的包袱,也不需要先从普通函数转换,但它们在行为上完全相同。

于 2015-09-12T05:40:50.733 回答
32

有几点不同:

  • 无法构造箭头函数。虽然箭头函数和绑定函数都没有.prototype属性,但前者在调用时会抛出异常,new而后者只是忽略绑定值并将其目标函数作为构造函数调用(尽管使用部分应用的绑定参数)在新实例上。

    function F() {}
    var f = () => {},
        boundF = F.bind({});
    console.log(new boundF(), new boundF instanceof F) // {}, true
    console.log(new f) // TypeError
    
  • 箭头函数确实有 lexical argumentsnew.target并且super也有(不仅仅是 lexical 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()在生成器函数上使用,但无法使用箭头函数来表达这一点。

于 2015-09-12T13:34:06.153 回答
9

这是另一个微妙的区别:

箭头函数可以在不使用“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}
于 2017-07-24T09:59:08.403 回答