【问题标题】:Confusion about Function.prototype.bind()关于 Function.prototype.bind() 的困惑
【发布时间】:2012-08-01 14:11:29
【问题描述】:

我是 ES5 的 Function.prototype.bind 和柯里化参数(基本上是为函数创建默认参数)的忠实粉丝。

我只是在胡闹,但我终其一生都无法弄清楚我自己的构造。这是我的游乐场:

function hello( arg1, arg2 ) {
    console.log('hello()');
    console.log('"this" is: ', this);
    console.log('arguments: ', arguments);
}

var foo = Function.prototype.call.bind( hello,{what: 'dafuq'}, 2 );
foo( 42 );

日志输出如下:

hello()
"this" is: Object{ what="dafuq" }
arguments: [2,42]

但我不明白{what: 'dafuq'} 对象究竟是如何成为foothis 的参考的。据我了解,我们正在为Function.prototype.call 创建一个绑定调用。让我们快速查看 .bind() 的 MDN 概要:

fun.bind(thisArg[, arg1[, arg2[, ...]]])

所以,thisArg for .callhello 函数,后跟参数列表。基本上发生的事情是这样的

Function.prototype.call.call( hello, {what: 'dafuq'}, 2);

...uuhhh 现在我的大脑有点痛。我想我现在知道会发生什么了,但是请有人找到很好的可靠词来详细解释它。

  • {what: 'dafuq'} 如何变成this reference

【问题讨论】:

    标签: javascript bind ecmascript-5 partial-application


    【解决方案1】:

    你不是在打电话给.bind(thisArg, args),而是
    Function.prototype.bind.call(thisArgUsedByCall, thisArgUsedByBind, argument)

    显示发生情况的不同方式:

    // thisArgUsedByCall is a function
    Function.prototype.call(thisArgUsedByCall, ...)   // does the same as:
    thisArgUsedByCall.bind(thisArgUsedByBind, argument);
    

    【讨论】:

      【解决方案2】:

      但我不明白 {what: 'dafuq'} 对象究竟是如何成为 foo 中 this 的参考

      这是因为foo 实际上是call 方法,其中hello 函数绑定为调用上下文,该对象绑定为第一个参数。 .call 的第一个参数设置其调用上下文的调用上下文。由于你已经绑定了它,这意味着该对象始终是调用上下文。


      这样说……

      您已将.call 的调用上下文绑定到hello

      这实际上与做......

         hello.call();
      // or...
      // Function.prototype.call.call(hello);
      

      您还将.call 的第一个参数绑定到{what: "dafuq"},所以这实际上与做...

      hello.call({what: "dafuq"});
      // or...
      // Function.prototype.call.call(hello, {what: "dafuq"});
      

      最后,您已将.call 的第二个参数绑定到2,所以这实际上与执行...

      hello.call({what: "dafuq"}, 2);
      // or...
      // Function.prototype.call.call(hello, {what: "dafuq"}, 2);
      

      【讨论】:

      • 是的 foo 是调用方法,但我们从不调用 foo.call( thisArg ) 对吗?我们直接通过() 调用它。我不明白:p
      • @jAndy:您使用.bind.call 的第一个参数绑定到您的对象。因此,由于.call 的这个“版本”有一个绑定的第一个参数,它总是将它用作调用上下文。
      • .call() 的绑定“版本”应该有 hello 作为 thisArg,不是吗?之后,我们执行绑定.call(),只是传入形式参数。哦,可能我只是在这里精神受阻,还在想它。
      • @jAndy:您已将.call 的调用上下文绑定到hello。这实际上与hello.call() 相同。您已将 call 的第一个参数绑定到 {what: "dafuq"}。所以这实际上与hello.call({what: "dafuq"}) 相同。最后,您将.call 的第二个参数绑定到2,因此这实际上与hello.call({what: "dafuq"}, 2) 相同
      • @jAndy:不客气。我正在用这个解释更新我的答案。
      【解决方案3】:

      简短的回答是,bind 使用第一个参数并将其用作 this,但随后 call 使用 its 第一个参数(这是 bind 的第二个参数)。

      绑定工作如下:

      fun.bind(thisArg, argArgs...)(x, y, ...)
      

      变成

      fun(argArgs..., x, y, ....) // this = thisArg
      

      所以

      foo( 42 )
      

      Function.prototype.call.bind( hello, { what: 'dafuq' }, 2 ) ( 42 )
      

      变成了

      Function.prototype.call({ what: 'dafuq' }, 2, 42) // this = hello
      

      调用是这样的:

      fun.call(thisArg, argArgs)
      

      变成

      fun(argArgs) // this = thisArg
      

      所以

      call({ what: 'dafuq' }, 2, 42) // this = hello
      

      变成

      hello(2, 42) // this = { what: 'dafuq' }
      

      【讨论】:

      • “(我不知道那个 5 是从哪里来的)” - 哪五个?
      • 看起来它已修复 - 这是主帖子中的错字。作为回报,我编辑了我的回复。
      猜你喜欢
      • 2019-05-17
      • 2020-03-06
      • 2016-03-16
      • 2013-07-27
      • 1970-01-01
      • 2012-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多