2008-12-04 17 views
34

Estoy trabajando con un poco de código html y Javascript que he tomado de otra persona. La página vuelve a cargar una tabla de datos (a través de una solicitud asincrónica) cada diez segundos, y luego vuelve a generar la tabla usando algún código DOM. El código en cuestión es como la siguiente:Controladores de eventos dentro de un bucle de Javascript: ¿necesita un cierre?

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

Cuando el evento onchange es despedido por un elemento <select> Sin embargo, parece que los mismos valores se pasan al método onStatusChanged() para cada <select> en la tabla (I' Hemos verificado que en cada iteración del ciclo, callid y anotherid reciben valores nuevos y distintos.

Sospecho que esto ocurre debido a la naturaleza de cómo configuro el controlador de eventos, con la sintaxis select.onchange = function(). Si entiendo cómo funciona esto correctamente, esta sintaxis establece un cierre para que el evento onchange sea una función que hace referencia a estas dos referencias, que terminan teniendo un valor final de lo que sea que estén configuradas en la última iteración del ciclo. Cuando se desencadena el evento, el valor al que se hace referencia en 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 que pueda copiar el valor de los parámetros que estoy pasando al onStatusChanged()?

He cambiado el título para reflejar mejor la pregunta y la respuesta aceptada.

Respuesta

49

De hecho, necesita implementar un cierre aquí. Esto debería trabajo (que me haga saber - No he probado es)

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

este trabaja de hecho - gracias! –

+0

Otra solución que descubrí, una solución, en realidad, sería almacenar callid y anotherid como atributos en el elemento DOM, y dentro del manejador de eventos solo hacer referencia a estos a través de this.getAttribute() –

+0

No lo llamaría una solución alternativa. Lo que esperaría es tener el controlador establecido una vez (no todas las veces a través del ciclo) y hacer que descubra las variables en sí. – dkretz

Cuestiones relacionadas