javascript 循环中赋值方法的行为非常奇怪

qij5mzcb  于 2023-01-04  发布在  Java
关注(0)|答案(3)|浏览(142)

请看下面的代码:

<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”。
我做错了什么?这对我来说是个巨大的阻碍。

ltskdhd1

ltskdhd11#

最后一个值被存储,你可以使用闭包:

<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绑定到函数作用域,关键的技巧是在循环中执行函数,否则,您将得到迭代并警告i的最后一个值的最终结果。
参考:http://www.jibbering.com/faq/faq_notes/closures.html

nlejzf6q

nlejzf6q2#

这个blog post很好地解释了这个问题,问题是在JavaScript中循环没有自己的变量作用域,所以内部函数使用父函数的作用域。

knsnq2tg

knsnq2tg3#

不要用for (… in …)来表示数组,而是使用简单的for循环:

for (var i=0; i<buttons.length; ++i) {
    actions[buttons[i]] = (function(i) {
        return function() {
            alert(i);
        };
    })(i);
}

相关问题