Javascript 循环内的事件处理程序 - 需要关闭吗?

IT技术 javascript dom loops closures
2021-01-20 05:48:57

我正在处理一些从别人那里接过来的 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>元素然而,好像被传递到相同的value观onStatusChanged()为每一个方法<select>在表中(我已经验证,在循环的每次迭代,callid并且anotherid被赋予了新的,不同的值)。

我怀疑这是由于我使用select.onchange = function()语法设置事件处理程序的方式的性质而发生的如果我理解这是如何正确工作的,这个语法将 onchange 事件的闭包设置为一个函数,该函数引用这两个引用,最终具有它们在循环的最后一次迭代中设置的最终值。当事件触发时,通过value参考callid,并anotherid在最后一次迭代的值而定,无法将值设置在单独的迭代。

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

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

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);
}
我发现的另一个解决方案 - 一种解决方法,真的 - 将 callid 和 anotherid 作为属性存储在 DOM 元素中,在事件处理程序中只需通过 this.getAttribute() 引用这些
2021-04-01 05:48:57
我不会称之为解决方法。我期望的是让处理程序设置一次(不是每次都通过循环)并让它发现变量本身。
2021-04-01 05:48:57
请注意,OP 也有一个闭包。并且实际上 OP 具​​有更具代表性的形式,您的闭包与其他闭包共享其环境(每次循环运行创建一个闭包)。但这正是产生意想不到效果的原因。
2021-04-10 05:48:57