Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript ES6 arrow函数和使用Function.prototype.bind绑定的函数之间有什么区别(如果有)?_Javascript_Ecmascript 6_Arrow Functions_Function Binding - Fatal编程技术网

Javascript ES6 arrow函数和使用Function.prototype.bind绑定的函数之间有什么区别(如果有)?

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,可能在最初创建之后很长

在我看来,在ES6中,以下两个功能几乎相同:

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
    的工作方式对于绑定函数没有多大意义

  • 箭头函数无权访问普通JavaScript函数可以访问的特殊
    参数
    对象

    (() => 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,在你的回答中,你应该明确提到接受父母的背景。我认为这不是一个特别有用的答案。是的-大括号可以省略-这很方便,但这只是语法上的差异,而不是功能上的差异。我认为这是一个很好的答案,特别是如果你不懂所有的速记语法