36

我正在处理一些我从别人那里接手的 html 和 Javascript 代码。该页面每十秒重新加载一个数据表(通过异步请求),然后使用一些 DOM 代码重新构建该表。有问题的代码如下所示:

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);
}

然而,当onchange为一个元素触发事件<select>时,似乎相同的值被传递给表中onStatusChanged()每个的方法<select>(我已经验证了在循环的每次迭代中,callid并被anotherid赋予了新的、不同的值)。

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

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

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

4

2 回答 2

50

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

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);
}
于 2008-12-04T19:30:47.397 回答
0

只需将 for 循环中的“var”更改为“let”,它就像一个魅力。

参考:JavaScript For 循环点击事件解决方案#4

于 2022-01-28T05:50:59.487 回答