关于dom:Javascript循环中的事件处理程序 – 需要一个闭包吗?

Event handlers inside a Javascript loop - need a closure?


我正在处理一些我从其他人手中接过的HTML和Javascript代码。该页面每十秒重新加载一个数据表(通过异步请求),然后使用一些DOM代码重新构建表。有问题的代码看起来像这样:

1
2
3
4
5
6
7
8
9
10
var blah = xmlres.getElementsByTagName('blah');
for(var i = 0; i < blah.length; i++) {
    var td = document.createElement('td');
    var select = document.createElement('select');
    select.setAttribute("...","...");
    select.onchange = function() {
        onStatusChanged(select, callid, anotherid);
    };
    td.appendChild(select);
}


但是当为传递给onStatusChanged()方法的相同值(我已经在每次迭代中验证了循环,callidanotherid被赋予新的,不同的值)。


我怀疑这是因为我使用select.onchange = function()语法设置事件处理程序的本质。如果我理解这是如何正常工作的,那么这个语法将onchange事件的闭包设置为一个函数,该函数引用这两个引用,最终得到它们在循环的最后一次迭代中设置的最终值。触发事件时,callidanotherid引用的值是上次迭代中设置的值,而不是单个迭代中设置的值。


有没有办法可以复制我传递给onStatusChanged()的参数值?


我更改了标题以更好地反映问题和接受的答案。



确实,你需要在这里实现一个闭包。 这应该工作(让我知道 - 我没有测试它)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var blah = xmlres.getElementsByTagName('blah');
for(var i = 0; i < blah.length; i++) {
    var td = document.createElement('td');
    var select = document.createElement('select');
    select.setAttribute("...","...");
    select.onchange = function(s,c,a)
    {
        return function()
        {
            onStatusChanged(s,c,a);
        }
    }(select, callid, anotherid);
    td.appendChild(select);
}