Vielleicht meintest du
myButton.onclick = function() {Spielzug(1,Punkte);}
- aber das hat auch den in diesem Fall unerwünschten Nebeneffekt, dass der zum Zeitpunkt der Zuweisung aktuelle Wert der Variablen Punkte in einer Closure eingeschlossen wird, und der Eventhandler somit nicht mit dem zum Zeitpunkt des Events gültigen Variablenwerts aufgerufen wird.
Nein, das genaue Gegenteil ist der Fall!
Zur Terminologie siehe http://molily.de/javascript-core/.
Eine Closure konserviert nicht den Wert, den eine Variable einer äußeren Funktion zum Zeitpunkt des Erzeugens der Closure hat. Sie konserviert die Ausführungskontexte und damit die Variablenobjekte der äußeren Funktionen über deren Ausführung hinaus. Konservieren heißt hier nicht Einfrieren der Werte, sondern dass die Verfügbarkeit erhalten bleibt, also die Scope Chain dieselbe bleibt.
Über die Scope Chain sind also immer ein und dieselben »freien« Variablen erreichbar. Nach dem Erzeugen der Closure kann diese oder eine andere Closure die freien Variablen ändern, sodass jede der Closures auf den *geänderten* Wert Zugriff hat.
Andernfalls würde folgendes nicht gehen:
var module = (function äußerefunktion () {
var priv = 0;
return {
inc : function closure1 () {
priv++
},
print : function closure2 () {
alert(priv);
}
};
})();
module.print(); // 0
module.inc();
module.print(); // 1
Wenn die Closures hier den *Wert* konservieren würden, den die Variable priv aus der äußeren Funktion zum Zeitpunkt des Erzeugens der Closure hätte, müsste beide Male 0 herauskommen.
Dass nicht der Fall ist, ist kein »unerwünschter Nebeneffekt«, sondern i.d.R. der Grund, warum man eine Closure anlegt: Nämlich private Objekte, die zwischen verschiedenen Funktionen geteilt und verändert werden – oben am Beispiel des Module Patterns demonstriert.
Die beiden Closures inc und print teilen sich über ihre Scope Chain den Zugriff auf denselben Ausführungskontext von äußerefunktion und damit auf die Variable priv. Damit können sie beide auf dieselbe Variable zugreifen und so miteinander kommunizieren.
Das kann natürlich zu Problemen führen, etwa mit Schleifen, siehe http://molily.de/javascript-core/#closures.
(function () {
var aElems = document.getElementByTagName('a');
for (var i = 0, l = aElements.length; i < l; i++) {
aElems.onclick = function () {
alert(i);
};
}
})();
Egal welches Element man anklickt, es wird immer dieselbe Variable ausgegeben. Diese hat nur einen Wert, nämlich aElements.length - 1, also der des letzten Schleifendurchlaufs.
Es gibt verschiedene Ansätze, diese Aufgabe zu lösen. Die universellste ist, mit jedem Schleifendurchlauf zwei Funktionen zu erzeugen, eine individuelle äußere Funktion, welche einen Parameter bekommt, der sich später nicht mehr ändert, sowie darin eine Closure. Das nennt sich Currying und ist auch mit Function.prototype.bind (ECMAScript 5) möglich:
(function () {
function handler (i) {
alert(i);
}
var aElems = document.getElementByTagName('a');
for (var i = 0, l = aElements.length; i < l; i++) {
var a = aElems[i];
a.onclick = handler.bind(a, i);
}
})();
Mathias