Controladores de eventos dentro de un bucle de Javascript: ¿necesitan un cierre?
Estoy trabajando con un poco de código HTML y Javascript que tomé de otra persona. La página recarga una tabla de datos (mediante una solicitud asincrónica) cada diez segundos y luego reconstruye la tabla usando algún código DOM. El código en cuestión se parece a esto:
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);
}
Sin embargo, cuando onchange
se activa el evento para un <select>
elemento, parece que se pasan los mismos valores al onStatusChanged()
método para cada uno <select>
en la tabla (lo he verificado en cada iteración del bucle callid
y anotherid
se me están dando valores nuevos y distintos).
Sospecho que esto ocurre debido a la naturaleza de cómo configuro el controlador de eventos, con la select.onchange = function()
sintaxis. Si entiendo cómo funciona esto correctamente, esta sintaxis establece un cierre para que el evento onchange sea una función que se refiere a estas dos referencias, que terminan teniendo un valor final de lo que sea que estén configurados en la última iteración del ciclo. Cuando se activa el evento, el valor al que hace referencia callid
y anotherid
es el valor establecido en la última iteración, no el valor establecido en la iteración individual.
¿Hay alguna manera de copiar el valor de los parámetros a los que estoy pasando onStatusChanged()
?
Cambié el título para reflejar mejor la pregunta y la respuesta aceptada.
De hecho, es necesario implementar un cierre aquí. Esto debería funcionar (avíseme, no lo probé)
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);
}