请参考JSfiddle - http://jsfiddle.net/r0ejq8h8/
var buttons = document.getElementsByTagName("button");
for (i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("click", function () {
alert("You just clicked " + i);
});
}
它总是警告“你刚刚点击了5”。我理解这一点。这个问题可能有很多解决方案。我找到的其中一个就是JSfiddle。在网上没有任何解释是足够好的。有人可以详细向我解释“i”发生了什么。任何其他有解释的解决方案也会很棒。
答案 0 :(得分:1)
最简单的方法是根据时间表来考虑这一点。
i
是一个指向值的变量名。当你经历循环(第一件事)时,我会不断重置为更高的值(先是0,然后是1等)。每次迭代时,都会将函数绑定到按钮。该函数尚未调用,它引用i
。
稍后,当单击一个按钮时,该函数将执行并查找i
的值。由于此时循环已完成,i
将等于按钮数(在本例中为5)。
基本上是这样的:
i
设为0
第一个函数被绑定
i
设为1
第二个函数已绑定
...
i
设置为n(按钮数量)
i
大于循环条件且循环完成
用户点击按钮
触发了回调并且引用i
当前设置为n
警告会以n为值进行触发。
有很多方法可以解决这个问题。最简单的旧(向后兼容方式)是将当前值传递给函数(因此立即读取),然后使用它返回一个新函数,该函数将旧值保存在闭包中:
for (i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("click", createHandler(i));
}
function createHandler(val) {
return function() {
alert("You just clicked " + val);
}
}
在所有浏览器中可能不起作用的新(ES6)方法是使用let,它限制变量以阻止范围。
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("click", function () {
alert("You just clicked " + i);
});
}
答案 1 :(得分:0)
单击该按钮时,会在单击该按钮时提醒i
的值。
这将在循环结束并且i
处于其最高值之后。
这是因为i
由您传递给addEventListener
的匿名函数关闭。
通过使用其他功能,您可以在调用该功能时复制i
的值。
var buttons = document.getElementsByTagName("button");
for (i = 0; i < buttons.length; i++) {
add_event_handler(buttons[i], i);
}
function add_event_handler(element, value_to_alert) {
element.addEventListener("click", function () {
alert("You just clicked " + value_to_alert);
});
}
<button>X</button>
<button>X</button>
<button>X</button>
<button>X</button>
答案 2 :(得分:0)
举个例子,
var buttons = document.getElementsByTagName("button");
for (i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("click", function () {
alert("You just clicked " + i);
});
}
您为click
button
事件注册的匿名函数包含值i
。所有人都共享相同的变量i
,并且将具有最近的值,该值已在for循环结束时更新。这就是为什么click事件总是警告You just clicked 5
var buttons = document.getElementsByTagName("button");
function createAlert(i) {
return function() {
alert("You just clicked " + i);
}
}
for (i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("click",createAlert(i));
}
在此修复程序中,alert
函数现在取决于createAlert
函数创建的环境。因此,对于每次迭代,返回的function
中的每一个都将包含由i
循环的迭代给出的for
的特定值