代码之家  ›  专栏  ›  技术社区  ›  matt b

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

  •  36
  • matt b  · 技术社区  · 16 年前

    我正在使用从别人那里接管的一些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() 每个人的方法 <选择> 在表中(我已经验证了在循环的每次迭代中, callid anotherid 被赋予新的、独特的值)。

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

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

    我更改了标题,以更好地反映问题和公认的答案。

    2 回复  |  直到 15 年前
        1
  •  50
  •   Peter Bailey    16 年前

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

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