Die Verschlüsse sind einfach:
Das folgende einfache Beispiel deckt alle wichtigen Punkte von JavaScript-Schließungen ab. *
Hier ist eine Fabrik, die Taschenrechner herstellt, die addieren und multiplizieren können:
function make_calculator() {
var n = 0; // this calculator stores a single number n
return {
add: function(a) {
n += a;
return n;
},
multiply: function(a) {
n *= a;
return n;
}
};
}
first_calculator = make_calculator();
second_calculator = make_calculator();
first_calculator.add(3); // returns 3
second_calculator.add(400); // returns 400
first_calculator.multiply(11); // returns 33
second_calculator.multiply(10); // returns 4000
Der springende Punkt: Jeder Aufruf von make_calculator
erstellt eine neue lokale Variable n
die weiterhin von diesem Rechner verwendet werden kann add
y multiply
funktioniert noch lange nach make_calculator
zurück.
_Wenn Sie mit Stack Frames vertraut sind, erscheinen Ihnen diese Rechner seltsam: Wie können sie ständig auf n
後 make_calculator
zurück? Die Antwort besteht darin, sich vorzustellen, dass JavaScript keine "Stack-Frames", sondern "Heap-Frames" verwendet, die auch nach der Rückkehr des Funktionsaufrufs, der sie erzeugt hat, bestehen bleiben können._
Innere Funktionen wie add
y multiply
die auf Variablen zugreifen, die in einer äußeren Funktion deklariert sind ** werden genannt Verschlüsse .
Das ist so ziemlich alles, was es an Schließungen gibt.
* Sie deckt zum Beispiel alle Punkte des Artikels "Closures for Dummies" ab, der in eine weitere Antwort mit Ausnahme von Beispiel 6, das einfach zeigt, dass Variablen verwendet werden können, bevor sie deklariert werden, was zwar gut zu wissen ist, aber nichts mit Schließungen zu tun hat. Es deckt auch alle Punkte in die akzeptierte Antwort Mit Ausnahme der Punkte (1), dass Funktionen ihre Argumente in lokale Variablen (die benannten Funktionsargumente) kopieren, und (2) dass das Kopieren von Zahlen eine neue Zahl erzeugt, das Kopieren einer Objektreferenz jedoch eine weitere Referenz auf dasselbe Objekt ergibt. Auch das ist gut zu wissen, hat aber wiederum nichts mit Schließungen zu tun. Es ist auch sehr ähnlich zu dem Beispiel in diese Antwort aber ein bisschen kürzer und weniger abstrakt. Er umfasst nicht den Punkt der diese Antwort o dieser Kommentar ist, dass JavaScript es schwierig macht, die actual Wert einer Schleifenvariablen in Ihre innere Funktion: Der Schritt des "Einfügens" kann nur mit einer Hilfsfunktion erfolgen, die Ihre innere Funktion umschließt und bei jeder Schleifeniteration aufgerufen wird. (Streng genommen greift die innere Funktion auf die Kopie der Variablen in der Hilfsfunktion zu und nicht auf etwas, das eingesteckt wurde). Auch dies ist sehr nützlich bei der Erstellung von Closures, aber nicht Teil dessen, was ein Closure ist oder wie es funktioniert. Zusätzliche Verwirrung entsteht dadurch, dass Closures in funktionalen Sprachen wie ML anders funktionieren, wo Variablen an Werte und nicht an Speicherplatz gebunden sind. Das sorgt für einen ständigen Strom von Leuten, die Closures auf eine Art und Weise verstehen (nämlich das "Einstecken"), die für JavaScript einfach falsch ist, wo Variablen immer an Speicherplatz und nie an Werte gebunden sind.
** Jede äußere Funktion, wenn mehrere verschachtelt sind, oder sogar im globalen Kontext, wie diese Antwort weist deutlich darauf hin.