【发布时间】:2012-04-07 11:13:54
【问题描述】:
我有一些代码生成一堆button 元素,并通过一些DOM 函数将它们附加到body 中的div。它动态地将一堆匿名函数(事件处理程序)设置为每个button的onclick事件。
这是通过从0 迭代到20 来执行的。
问题是,我想在事件处理程序中使用循环计数器i——但是,它在循环中的迭代中的值不是i 达到的最终值。起初,我认为我可以通过关闭来做到这一点,但后来我意识到它并没有像我最初想象的那样执行。 i 每次迭代都在不断变化,所有其他匿名函数(通过闭包?)必须看到相同的 i,因为它的范围内的 i 都指向相同的值。因为当您触发onclick 时它们都报告相同的值。
所以我想,我该如何解决这个问题?我尝试将i 设置为另一个变量等等,但所有结果都相同,因为该新变量的值在每次迭代时都会像i 一样更新。我想我在这里遗漏了一些简单的东西。
<!DOCTYPE html>
<html>
<head>
<title>loop closure test</title>
<script language="javascript" type="text/javascript">
window.onload = function() {
var div = document.getElementById("myDiv");
for( var i = 0; i <= 20; i++ ) {
var b = document.createElement("button");
b.setAttribute("type","button");
b.appendChild(document.createTextNode("Button" + i.toString()));
b.onclick = function(event) {
var date = new Date( 2012, 3, i );
alert( date.getMonth() + "/" + date.getDate() + "/" + date.getFullYear() );
}
div.appendChild(document.createElement("br"));
div.appendChild(b);
}
}
</script>
</head>
<body>
<div id="myDiv"></div>
</body>
</html>
我想了更多,下面的示例答案。基本上我需要将i 困在另一个闭包中。我决定走这条路:
<!DOCTYPE html>
<html>
<head>
<title>loop closure test</title>
<script language="javascript" type="text/javascript">
window.onload = function() {
var div = document.getElementById("myDiv");
for( var i = 0; i <= 20; i++ ) {
div.appendChild( (function() {
var day = i;
var b = document.createElement("button");
b.setAttribute("type","button");
b.appendChild(document.createTextNode("Button" + i.toString()));
b.onclick = function(event) {
var date = new Date( 2012, 3, day );
alert( date.getMonth() + "/" + date.getDate() + "/" + date.getFullYear() );
}
return b;
}()));
div.appendChild(document.createElement("br"));
}
}
</script>
</head>
<body>
<div id="myDiv"></div>
</body>
</html>
【问题讨论】:
-
是的,它可以在每个循环中使用闭包。
-
要知道的关键是 JavaScript 局部变量的作用域是函数级别。因此,如果你想给每个处理程序自己的“i”,你需要在 another 函数中实例化处理程序函数。关于这个问题有很多很多 StackOverflow 问题。
-
@Pointy 这根本不是 jQuery,你链接的问题对我来说完全陌生。
-
不管你是否使用jQuery,这都是同一个问题;毕竟,jQuery 只是 JavaScript。
标签: javascript loops dom closures dom-events