Javascript 将特定上下文绑定到事件处理程序:理解函数上下文、返回语句和闭包?

Javascript 将特定上下文绑定到事件处理程序:理解函数上下文、返回语句和闭包?,javascript,functional-programming,closures,anonymous-function,Javascript,Functional Programming,Closures,Anonymous Function,我正在阅读John Resig的《Javascript忍者的秘密》,他在书中谈到了如何更改事件处理程序的上下文。其中他有以下代码。我不知道它为什么有效。这一次我很迷茫 在下一个例子中,我将讨论javascript的本机“bind”函数 elem.addEventListener("click",button.click.bind(button),false); 就我所见,下一条语句将是John Resig的bind()函数返回的内容 elem.addEventListener

我正在阅读John Resig的《Javascript忍者的秘密》,他在书中谈到了如何更改事件处理程序的上下文。其中他有以下代码。我不知道它为什么有效。这一次我很迷茫

在下一个例子中,我将讨论javascript的本机“bind”函数

    elem.addEventListener("click",button.click.bind(button),false); 
就我所见,下一条语句将是John Resig的bind()函数返回的内容

    elem.addEventListener("click",function() { button.click.apply(button, arguments)},false); 
但是等等,John Resig的bind函数中有两个返回语句。在这一点上,我只是猜测-下一个呢

    elem.addEventListener("click",function() { return button.click.apply(button, arguments)},false); 
上述陈述都不起作用

其次,为什么bind函数有两个返回语句?在我看来,bind的工作原理如下:

function bind(context,name){ 
            return function(){ context[name].apply(context,arguments); }; 
          }
第三,如果我使用John Resig的bind函数并尝试将其分配给变量,比如变量ninja,如下所示:

var ninja = bind(button,"click");
ninja;
我希望看到返回给我的函数如下所示:

function(){ button["click"].apply(button,arguments);
因为上下文和名称的值将通过闭包填充。但实际上它看起来像:

function(){ context[name].apply(context,arguments);

所以…我希望我对所有这些问题感到困惑的根本原因来自于我所缺少的同一个基本概念。想法?

这是很多问题!我会尽力帮你澄清这一点

  • addEventListener
    要求函数引用作为第二个参数。当您将其传递给
    按钮。单击.apply(按钮)
    时,您将立即返回,并将单击函数的返回值(
    示例中未定义的
    )传递给
    addEventListener
    。这就是它不起作用的原因

  • 另一方面,
    bind
    返回一个函数,因此调用它来获取事件侦听器函数是合适的

  • 您的示例使用了,并且它后面的示例尝试模拟本机
    bind

如果我删除bind()函数并尝试任何操作,我总是会收到错误消息“clicked is undefined”

这是因为您的
按钮。单击
功能有缺陷。它访问一个未定义的变量
单击的
。只有在无意中使用的全局对象调用函数时(如
按钮。单击.call(窗口)
),然后
this.clicked=true
创建一个可在此后访问的全局变量。将函数更改为

    alert('It has been clicked! The value of clicked is ' + this.clicked);
//                                                          ^^^^^
你的每一种方法都会奏效

但是等等,John Resig的bind函数中有两个返回语句

Resig示例中的内部
返回将是事件侦听器的最终返回。因此,例如,如果要防止单击处理程序上的默认值,可以使其
返回false
。如果没有内部
返回
,事件侦听器将返回
未定义
,而不是转发代理侦听器函数返回的内容。对于您的示例来说,这不是必需的,但在用于时,这是
bind
函数的一个有价值的特性

我希望看到返回给我的函数如下所示


最后,关于闭包混淆:闭包是一个函数,它从外部作用域保留对内容的引用(基本上所有函数都在js中这样做)。但是引用并没有像您在示例中所期望的那样,用
按钮[“click”]
替换函数体代码。在Resigs
bind
返回的函数中,
context[name]
表示
按钮[“click”]
,但代码实际上没有被替换<代码>上下文
指向
按钮
,而
名称
持有字符串
“单击”

,问题太多了!我会尽力帮你澄清这一点

  • addEventListener
    要求函数引用作为第二个参数。当您将其传递给
    按钮。单击.apply(按钮)
    时,您将立即返回,并将单击函数的返回值(
    示例中未定义的
    )传递给
    addEventListener
    。这就是它不起作用的原因

  • 另一方面,
    bind
    返回一个函数,因此调用它来获取事件侦听器函数是合适的

  • 您的示例使用了,并且它后面的示例尝试模拟本机
    bind

如果我删除bind()函数并尝试任何操作,我总是会收到错误消息“clicked is undefined”

这是因为您的
按钮。单击
功能有缺陷。它访问一个未定义的变量
单击的
。只有在无意中使用的全局对象调用函数时(如
按钮。单击.call(窗口)
),然后
this.clicked=true
创建一个可在此后访问的全局变量。将函数更改为

    alert('It has been clicked! The value of clicked is ' + this.clicked);
//                                                          ^^^^^
你的每一种方法都会奏效

但是等等,John Resig的bind函数中有两个返回语句

Resig示例中的内部
返回将是事件侦听器的最终返回。因此,例如,如果要防止单击处理程序上的默认值,可以使其
返回false
。如果没有内部
返回
,事件侦听器将返回
未定义
,而不是转发代理侦听器函数返回的内容。对于您的示例来说,这不是必需的,但在用于时,这是
bind
函数的一个有价值的特性

我希望看到返回给我的函数如下所示

最后,关于闭包混淆:闭包是一个函数,它从外部作用域保留对内容的引用(基本上所有函数都在js中这样做)。但是引用并没有像您在示例中所期望的那样,用
按钮[“click”]
替换函数体代码。在Resigs
bind
返回的函数中,
context[name]
表示
按钮[“clic
    alert('It has been clicked! The value of clicked is ' + this.clicked);
//                                                          ^^^^^
function bind(context,name){
    return function(){
      return context[name].apply(context,arguments);
    };
}
((function(){return button['click'].apply(button, arguments);})).apply(elm, arguments)
function(){
 context.name(arguments)
}