Обработчики событий внутри цикла 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()?

Я изменил название, чтобы лучше отразить вопрос и принятый ответ.

2 ответа

Решение

Вам действительно нужно реализовать замыкание здесь. Это должно работать (дайте мне знать - я не проверял это)

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

Просто измените «var» в цикле for на «let», и все заработает.

ссылка: JavaScript For Loop Click Event Solution #4

Другие вопросы по тегам