2008-12-04 4 views
34

Ich arbeite mit ein wenig HTML und Javascript-Code, den ich von jemand anderem übernommen habe. Die Seite lädt alle zehn Sekunden eine Tabelle mit Daten (über eine asynchrone Anforderung) neu und erstellt dann die Tabelle unter Verwendung von DOM-Code neu. Der betreffende Code sieht ungefähr so ​​aus:Event-Handler innerhalb einer Javascript-Schleife - brauchen Sie eine Schließung?

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

Wenn das onchange Ereignis jedoch für ein <select> Element ausgelöst wird, wie es scheint, die gleichen Werte werden für jeden <select> in der Tabelle auf die onStatusChanged() Methode übergeben wird (I‘ habe verifiziert, dass in jeder Iteration der Schleife callid und anotherid neue, eindeutige Werte erhalten).

Ich vermute, dass dies aufgrund der Art der Einstellung des Ereignishandlers mit der select.onchange = function() Syntax auftritt. Wenn ich verstehe, wie dies richtig funktioniert, stellt diese Syntax eine Schließung für das onchange-Ereignis als eine Funktion ein, die sich auf diese beiden Referenzen bezieht, die letztendlich einen endgültigen Wert dessen haben, auf was sie in der letzten Iteration der Schleife eingestellt sind. Wenn das Ereignis ausgelöst wird, ist der von callid und anotherid referenzierte Wert der in der letzten Iteration festgelegte Wert und nicht der in der einzelnen Iteration festgelegte Wert.

Gibt es eine Möglichkeit, dass ich den Wert der Parameter kopieren kann, die ich an onStatusChanged() übergebe?

Ich habe den Titel geändert, um die Frage und die angenommene Antwort besser widerzuspiegeln.

Antwort

49

Sie müssen in der Tat eine Schließung hier implementieren. Diese sollte Arbeit (lassen Sie mich wissen - ich habe es nicht getestet)

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

tut dies tatsächlich funktioniert - danke! –

+0

Auch eine andere Lösung, die ich entdeckte - ein Workaround, wirklich - wäre, die Callid und eine andere als Attribute im DOM-Element zu speichern, und im Eventhandler verweisen Sie nur über this.getAttribute() –

+0

Ich würde es nicht eine Umgehung nennen. Was ich erwarten würde ist, dass der Handler einmal gesetzt wird (nicht jedes Mal durch die Schleife) und die Variablen selbst entdecken lassen muss. – dkretz