6
<input type="button" value="Button 1" id="btn1"  />
<input type="button" value="Button 2" id="btn2"  />
<input type="button" value="Button 3" id="btn3"  onclick="buttonClicked();"/>


<script type="text/javascript">  

  function buttonClicked(){        
    var text = (this === window) ? 'window' : this.id;    
    console.log( text);        
  }

  var button1 = document.getElementById('btn1');  
  var button2 = document.getElementById('btn2');


  button1.onclick = buttonClicked;

  button2.onclick = function(){
    buttonClicked();
  };

</script>

问题:

单击button1时,显示:btn1,单击button2和button3,显示:window,为什么不btn2btn3

4

2 回答 2

4
button1.onclick = buttonClicked;

它显示btn1因为 onclick(button1 的属性)现在指向buttonClicked,所以这个调用的上下文是button1

button2.onclick = function(){
    buttonClicked();
  };

它显示是window因为 onclick(button2 的属性)现在指向一个匿名函数,并且在您调用的函数内部buttonClicked();(类似于window.buttonClicked();),此调用的上下文是window

您使用 button3 的情况:

<input type="button" value="Button 3" id="btn3"  onclick="buttonClicked();"/>

相当于:

btn3.onclick = function(){
    buttonClicked();
}

因为当您在内联声明事件处理程序时,浏览器会自动将您的代码包装在匿名函数中。

于 2013-07-04T03:22:16.070 回答
1

基本

当单击处理程序定义如下:

button.onclick = some_function;

单击按钮时,JavaScript 将实际运行:

some_function.call(button, ...);

换句话说,对按钮元素的引用被绑定this在处理程序内部。

匿名函数

让我们看一下 click 处理程序的定义button2

button2.onclick = function() {
    buttonClicked();
}

匿名函数被绑定到按钮,但调用buttonClicked()根本没有被绑定(因此它隐式绑定到 的范围window)。要达到预期的结果,您需要这样做:

button2.onclick = function() {
    buttonClicked.apply(this, arguments);
}

排队

您在onclick属性中写入的任何内容都将用作单击处理程序的主体。所以你的代码:

<input ... onclick="some_function();" />

相当于:

button3.onclick = function() {
    some_function();
};

如您所见,它的行为与button2.

奖金

为了好玩,您可以像这样编写内联点击处理程序:

<input ... onclick="buttonClicked.call(this);" />

结果

顺便说一句,内联编写事件处理程序不是一个很好的做法,您应该查看使用addEventListener()attachEvent() (IE) 注册它们,但请注意它们的行为不同。

于 2013-07-04T03:31:17.100 回答