ES6箭头函数和与Function.prototype.bind绑定的函数之间有什么区别(如果有的话)?

Ale*_*ing 47 javascript ecmascript-6 function-binding arrow-functions

在我看来,在ES6,下面的两个功能都非常接近相同的:

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

() => {
  return this;
};
Run Code Online (Sandbox Code Playgroud)

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

显然,在一般意义上,Function.prototype.bind它比箭头函数更灵活:它可以绑定到本地以外的值this,并且它可以this在任何时间点绑定任何函数,可能在最初创建之后很长时间.不过,我不问如何bind本身就是从箭头的功能不同,我问箭头的功能是如何从立即调用不同bind使用this.

ES6中的两个结构之间是否有任何差异?

Ale*_*ing 34

没有(重大)差异.

嗯,好吧,这有点不成熟.箭头功能有三个独特的微小差异.

  1. 箭头功能不能用于new.

    当然,这意味着它们没有prototype属性,不能用于创建具有经典灵感语法的对象.

    new (() => {}) // TypeError: () => {} is not a constructor
    
    Run Code Online (Sandbox Code Playgroud)

    这可能是最好的,但是new对于绑定函数来说,工作方式没有多大意义.

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

    (() => arguments)(1, 2, 3) // ReferenceError: arguments is not defined
    
    Run Code Online (Sandbox Code Playgroud)

    这可能是一个问题.据推测,这是为了消除JavaScript的其他奇怪之处.arguments对象是自己的特殊兽,它有奇怪的行为,所以它并不奇怪,这是抛出.

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

    ((...args) => args)(1, 2, 3) // [1, 2, 3]
    
    Run Code Online (Sandbox Code Playgroud)
  3. 箭头函数没有自己的new.target属性,它们使用new.target它们的封闭函数(如果存在).

    这与删除箭头函数的"神奇"引入值的其他更改一致.new如上所述,考虑到箭头功能无论如何都不能使用,这种特别的变化是特别明显的.

否则,箭头就像绑定函数一样,在语义上.箭头可能更有效,因为它们不需要携带额外的行李,因为它们不需要首先从普通功能转换,但它们的行为完全相同.

  • @Bergi即使在严格模式下,`arguments`也很奇怪:它仍然不是一个数组,所以splat仍然更有用和可预测. (4认同)
  • 我不会说`arguments`被抛出是因为"奇怪的行为"(无论如何都以严格模式修复).相反,箭头函数可以访问它们的封闭函数的`arguments`对象,与它们访问`this`绑定和`new.target`的方式一致. (2认同)

Ber*_*rgi 28

有一些差异:

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

    function F() {}
    var f = () => {},
        boundF = F.bind({});
    console.log(new boundF(), new boundF instanceof F) // {}, true
    console.log(new f) // TypeError
    
    Run Code Online (Sandbox Code Playgroud)
  • 箭头函数确实有词法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;
    
    Run Code Online (Sandbox Code Playgroud)
  • 箭头函数不能是生成器函数(尽管它们可以返回生成器).您可以.bind()在生成器函数上使用,但无法使用箭头函数表达此函数.


Cho*_*ang 5

这是另一个细微的区别:

通过立即删除=>后的{}大括号,箭头函数可以不使用'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}
Run Code Online (Sandbox Code Playgroud)

  • 我不认为这是一个特别有用的答案。是的 - 可以省略大括号 - 这很方便,但这只是语法上的差异,而不是功能上的差异。 (2认同)