molily: Closures und Schleifen, Daten an eine Handler-Funktion übergeben

Beitrag lesen

Hallo,

links[x].setAttribute("onmouseover","myover(name)");

Man sollte dazu sagen, dass diese Möglichkeit nicht dazu führt, dass beim Mouseover die gewünschte Funktion ausgeführt wird - zumindest nicht in allen Browsern.

…oder du erstellst ein Event:

links[x].onmouseover = function(){myover(name);}

Man sollte dazu sagen, dass »name« hier garantiert nicht der gewünschte, in dem jeweiligen Schleifendurchgang in Erfahrung gebrachte Name ist.

Genauer gesagt wird in diesem Kontext eine Closure notiert (siehe auch):

for (var x = 0, link, name; x < links.length; x++) {  
   link = links[x];  
   name = link.firstChild.name;  
   link.onmouseover = function () { myover(name); };  
}

Es werden viele Funktionsobjekte erzeugt. Diese Funktionen haben nur deshalb Zugriff auf die Variable name, weil durch das Notieren der anonymen, inneren Funktion in der äußeren Funktion die lokalen Variablen der äußeren auch in der inneren verfügbar sind (das ist der Closure-Effekt).

Man hat in diesen vielen Funktionen also Zugriff auf die Variable name, aber deren Wert ist nicht der gewünschte. Der Wert ist - wie gesagt - der, den die Variable als letztes bei der Ausführung der äußeren Funktion (die mit der Schleife) hatte, also beim letzten Schleifendurchgang. Wenn der Wert z.B. »abc« ist, dann wird bei egal welchem Mouseover immer myover("abc") aufgerufen.

Das liegt daran, dass einfach die lokalen Scopes der Funktionen verknüpft werden. Die Namen zeigen in allen Funktionen auf dieselbe Speicherstelle, die auch nach der Ausführung der Funktion mit der Schleife erhalten bleibt. Das Problem von Closures und Schleifen hatte ich bereits hier erklärt:
</archiv/2006/9/t136283/#m885076>

Gut, wie kann man das Problem lösen?
Dazu hatte ich Alternativen beschrieben:
</archiv/2006/10/t138533/#m900197>
Und auch hier:
http://aktuell.de.selfhtml.org/artikel/javascript/organisation/#datenspeicherung

So kann es z.B. funktionieren:

for (var x = 0, link, name; x < links.length; x++) {  
   link = links[x];  
   link.name = link.firstChild.name;  
   link.onmouseover = myover;  
}  
...  
function myover (e) {  
   alert(this.name);  
}

Mathias