一尘不染

Javascript循环内的事件处理程序-是否需要闭包?

javascript

我正在处理从别人那里接手的一些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()

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


阅读 242

收藏
2020-04-25

共1个答案

一尘不染

实际上,您确实需要在此处实现闭包。这 应该可以 工作(让我知道-我没有测试过)

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);
}
2020-04-25