请考虑以下代码:
<a href="javascript:void(-1)" id="a1">a1</a>
<a href="javascript:void(-1)" id="a2">a2</a>
<script type="text/javascript">
var buttons = []
buttons.push("a1")
buttons.push("a2")
var actions = []
for (var i in buttons)
{
actions[buttons[i]] = function() { alert(i) }
}
var elements = document.getElementsByTagName("a")
for (var k = 0; k < elements.length; k++)
{
elements[k].onclick = actions[elements[k].id]
}
</script>
基本上,它显示了两个锚点a1和a2,我希望在单击相应的锚点时会在警报中弹出“1”和“2”。 它没有发生,点击其中任何一个时我得到“2”。在花了一个小时冥想代码之后,我决定它可能会发生,因为两个锚点的动态onclick方法保持“i”的最后一个值。 所以我将该循环更改为
for (var i in buttons)
{
var local_i = i.toString()
actions[buttons[i]] = function() { alert(local_i) }
}
希望每个动态函数都能获得具有立即值的“i”副本。但是在这个改变之后,当我点击任一链接时,我会弹出“1”。
我做错了什么?这对我来说是一个巨大的阻碍。
答案 0 :(得分:3)
存储最后一个值,您可以使用闭包:
<a href="#">blah</a><br>
<a href="#">blah</a><br>
<a href="#">foo</a><br>
<script>
(function() {
var anchors = document.getElementsByTagName('a');
for ( var i = anchors.length; i--; ) {
var link = anchors[i];
(function(i) {
link.onclick = function() {
alert(i)
}
})(i);
}
})();
</script>
此解决方案将i
绑定到函数作用域,关键技巧是在循环内部执行函数,否则将留下迭代的最终结果并警告{{的最后一个值1}}。
答案 1 :(得分:2)
这blog post很好地解释了这个问题。问题是循环在JavaScript中没有自己的变量作用域,因此内部函数使用父函数的作用域。
答案 2 :(得分:-1)
不要将for (… in …)
用于数组。请改用简单的for
循环:
for (var i=0; i<buttons.length; ++i) {
actions[buttons[i]] = (function(i) {
return function() {
alert(i);
};
})(i);
}