[英]JavaScript: Very strange behavior with assigning methods in a loop
Consider this code below: 请考虑以下代码:
<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>
Basically, it shows two anchors, a1 and a2, and I expect to see "1" and "2" popping up in an alert when clicking on corresponding anchor. 基本上,它显示了两个锚点a1和a2,并且我希望在单击相应的锚点时在警报中弹出“1”和“2”。 It doesn't happen, I get "2" when clicking on either.
它没有发生,点击其中任何一个时我得到“2”。 After spending an hour meditating on the code, I decided that it probably happens because dynamic onclick methods for both anchors keep the last value of "i".
在花了一个小时冥想代码之后,我决定它可能会发生,因为两个锚点的动态onclick方法保持“i”的最后一个值。 So I change that loop to
所以我将循环更改为
for (var i in buttons)
{
var local_i = i.toString()
actions[buttons[i]] = function() { alert(local_i) }
}
hoping that each dynamic function will get its own copy of "i" with immediate value. 希望每个动态函数都能获得具有立即值的“i”副本。 But after this change I get "1" popping up when I click on either link.
但是在这个改变之后,当我点击任一链接时,我会弹出“1”。
What am I doing wrong? 我究竟做错了什么? It's a huge show stopper for me.
这对我来说是一个巨大的表演限制。
The last value is stored, you can use closures for this: 存储最后一个值,您可以使用闭包:
<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>
This solution binds the i
to the function scope, the key trick is the executing of the function inside of the loop, otherwise you are left with the end result of iterating through and alerting the last value of i
. 这个解决方案将
i
绑定到函数作用域,关键技巧是在循环内部执行函数,否则你将留下迭代的最终结果并警告i
的最后一个值。
Reference: http://www.jibbering.com/faq/faq_notes/closures.html 参考: http : //www.jibbering.com/faq/faq_notes/closures.html
Don't use for (… in …)
for arrays. 不要
for (… in …)
数组。 Use the simple for
loop instead: 请改用简单的
for
循环:
for (var i=0; i<buttons.length; ++i) {
actions[buttons[i]] = (function(i) {
return function() {
alert(i);
};
})(i);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.