Gestori di eventi all’interno di un ciclo di Javascript – serve una chiusura?

Sto lavorando con un po ‘di codice HTML e Javascript che ho rilevato da qualcun altro. La pagina ricarica una tabella di dati (tramite una richiesta asincrona) ogni dieci secondi, quindi ricostruisce la tabella utilizzando un codice DOM. Il codice in questione è simile a questo:

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

Quando l’evento onchange viene triggersto per un elemento , tuttavia, sembra che gli stessi valori vengano passati al metodo onStatusChanged() per ogni nella tabella (ho verificato che in ogni iterazione del ciclo, callid e anotherid ricevono nuovi, distinti valori).

Sospetto che ciò avvenga a causa della natura di come sto impostando il gestore di eventi, con la select.onchange = function() . Se capisco come funziona correttamente, questa syntax imposta una chiusura affinché l’evento onchange sia una funzione che fa riferimento a questi due riferimenti, che finiscono per avere un valore finale di ciò a cui sono impostati sull’ultima iterazione del ciclo. Quando l’evento si callid , il valore referenziato da callid e anotherid è il valore impostato nell’ultima iterazione, non il valore impostato nella singola iterazione.

C’è un modo per copiare il valore dei parametri che sto passando a onStatusChanged() ?

Ho cambiato il titolo per riflettere meglio la domanda e la risposta accettata.

In effetti, è necessario implementare una chiusura qui. Questo dovrebbe funzionare (fammi sapere – non l’ho provato)

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