<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>
问题:
点击按钮1,显示:btn1
,点击按钮2和按钮3,显示:window,
为什么不btn2
,btn3
?
答案 0 :(得分: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();
}
因为当你内联声明你的事件处理程序时,浏览器会自动将你的代码包装在一个匿名函数中。
答案 1 :(得分:1)
<强>基本强>
当点击处理程序定义如下:
button.onclick = some_function;
单击按钮时,JavaScript实际上会运行此命令:
some_function.call(button, ...);
换句话说,对按钮元素的引用在处理程序中绑定为this
。
匿名函数
让我们看一下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)注册它们,但请注意它们的行为不同。