dedlfix: JavaScript Functionsreferenz bei onclick funktioniert nicht

Beitrag lesen

echo $begrüßung;

for (var i = 0; i < 3; i++)
               a.onclick = function () { showbox(i); };
Das Problem ist, dass die Variable i und nicht deren aktueller Wert in den Eventhandler-Code eingebaut wird. Die Auswertung des Codes im Eventhandler findet erst beim Aufrufen statt. i ist somit immer 3, so wie es am Ende der for-Schleife hinterlassen wurde. Allerdings fällt mir leider kein eleganterer Weg außer eval() ein, um das Problem zu lösen.
Als ich vor etwas Ähnlichem stand, habe ich das so ähnlich gelöst:

for (var i=0; i<3; i++){

a.onclick=(function(x){return function(){showbox(x);};})(i);}

  
Aha, sieht verwendbar aus. [Augenblicke später] Funktioniert auch, zumindest im FF 2.0.0.15.  
  

> Keine Verwendung von eval und die Closures, die einem hier den Streich spielen, werden sinnvoll eingesetzt. ;-)  
  
Ich versuche mal die Arbeitsweise zu erklären. Ein ()-Klammernpaar und die Semikolons sind übrigens überflüssig.  
  
  a.onclick = function (x) { return function () { showbox(x) } } (i)  
  
Deklariert wird eine anonyme Funktion, die einen Parameter entgegennimmt und in x zur Verfügung stellt. Das ist dieser Teil:  
  
  function (x) { ... }  
  
Diese wird auch sofort mit i als Parameter aufgerufen:  
  
  function (x) { ... } (i)  
  
Sie gibt per return eine weitere anonyme Funktion zurück, die den showbox-Aufruf enthält, der, wenn irgendwann später der Eventhandler zuschlägt, mit dem in x gemerkten Wert ausgeführt wird. Diese zweite anonyme Funktion wird dem Eventhandler zugewiesen.  
  
Die äußere anonyme Funktion geht im Prinzip verloren, da keine Referenz mehr auf sie besteht. Sie bleibt aber irgendwo im Speicher erhalten, weil sie das x enthält, welches die innere Funktion bekommt.  
  
Beim nächsten Schleifendurchlauf passiert das gleiche nochmal. Es wird eine neue äußere anonyme Funktion erstellt, die sofort mit dem nun um eins erhöhten Wert von i ausgeführt wird, usw. usf.  
  
  
echo "$verabschiedung $name";