Verschlüsse sind ein wichtiges Merkmal in JavaScript, und ihre größte Funktion besteht darin, Informationen während des Funktionsbetriebs zu sparen. In JavaScript werden viele Merkmale von Verschlüssen während der Funktionsaufrufe aus der Bereichskette abgeleitet.
Umfangskette von Funktionsaufrufobjekten und Variablen
Für jeden Funktionsaufruf in JavaScript erstellt JavaScript ein lokales Objekt, um die in der Funktion definierten lokalen Variablen zu speichern. Wenn es in der Funktion eine verschachtelte Funktion gibt, definiert JavaScript ein verschachteltes lokales Objekt auf dem bereits definierten lokalen Objekt. Für eine Funktion gibt es so viele Schichten verschachtelter Funktionsdefinitionen, wie es viele Schichten verschachtelter lokaler Objekte gibt, wie es gibt. Dieses lokale Objekt wird als "Funktionsaufrufobjekt" bezeichnet ("Call -Objekt" in ECMascript 3 und wurde in ECMascript 5 in "deklarative Umgebungsaufzeichnung" umbenannt, aber ich persönlich denke, dass der Name in ECMascript 3 einfacher zu verstehen ist). Die folgenden Funktionsaufrufe werden als Beispiel verwendet:
Die Codekopie lautet wie folgt:
Funktion f (x) {
var a = 10;
zurück ein*x;
}
console.log (f (6)); // 60
In diesem einfachen Beispiel erstellt JavaScript, wenn die Funktion f () aufgerufen wird, ein Anrufobjekt der Funktion f () (nennen wir es f_invokeobj). Es gibt zwei Eigenschaften im F_Invokeobj -Objekt: a und x; Wenn f () ausgeführt wird, beträgt der A -Wert 10 und der x -Wert 6, sodass das endgültige Rückgabeergebnis 60 beträgt. Die Abbildung lautet wie folgt:
Bei Funktionsnistern erstellt JavaScript mehrere Funktionen für Funktionsaufrufe:
Die Codekopie lautet wie folgt:
Funktion f (x) {
var a = 10;
zurückgeben a*g (x);
Funktion g (b) {
Rückkehr b*b;
}
}
console.log (f (6)); // 360
In diesem Beispiel erstellt JavaScript beim Aufrufen der Funktion f () ein Aufrufobjekt der Funktion f () (f_invokeobj), das zwei Attribute A und X hat, und der Wert A ist 10 und der Wert X ist 6; Beim Ausführen von f () wird JavaScript die Funktion g () in der Funktion f () analysieren und definieren und ein Aufrufobjekt von g () (g_invokeobj) erstellt, das ein Attribut B hat, und der Wert B ist der gleiche wie der übergebene Parameter X, sodass das endgültige Rückgabeergebnis 360 ist. Die Abbildung ist wie folgt: wie folgt:
Wie Sie sehen können, bildet der Funktionsaufrufobjekt eine Kette. Wenn die eingebettete Funktion g () ausgeführt wird und den variablen Wert erhalten muss, wird nach dem neuesten Funktionsaufrufobjekt gesucht. Wenn es nicht durchsucht werden kann, suchen Sie in einem weiteren Aufrufobjekt entlang der Funktionsaufrufobjektkette, bei dem es sich um die sogenannte "Bereichskette von Variablen" handelt. Wenn in den beiden Funktionsaufrufobjekten dieselbe Variable angezeigt wird, nimmt die Funktion den variablen Wert im Aufrufobjekt, der ihm am nächsten liegt:
Die Codekopie lautet wie folgt:
Funktion f (x) {
var a = 10;
zurückgeben a*g (x);
Funktion g (b) {
var a = 1;
return b*b*a;
}
}
console.log (f (6)); // 360, nicht 3600
Im obigen Beispiel hat die Variable A unterschiedliche Werte im aufrufenden Objekt (g_invokeobj) der G () -Funktion und des aufrufenden Objekts (f_invokeobj) der Funktion f (). Beim Ausführen der G () -Funktion beträgt der Wert einer in der g () -Funktion verwendeten Funktion 1, während der Wert einer außerhalb der G () -Funktion verwendeten Funktion 1. Die Funktionsaufrufobjektkette zu diesem Zeitpunkt ist wie folgt:
Was ist eine Schließung?
Alle Funktionen in JavaScript sind Objekte, und beim Definieren von Funktionen wird eine entsprechende Funktionskette von Funktionsobjekten generiert. Eine Funktionsdefinition entspricht einer Funktionskette von Funktionsaufrufen Objekte. Solange das Funktionsobjekt existiert, besteht das entsprechende Funktionsaufrufobjekt. Sobald eine Funktion nicht mehr verwendet wird, wird das entsprechende Funktionsanrufobjekt Müll erfasst. und diese Kombination von Funktionsobjekten und der Kette des Funktionsaufrufobjekts wird als "Verschluss" bezeichnet. In den obigen Beispielen der Funktion f () und g () gibt es zwei Verschluss: das Funktionsobjekt f () und das Funktion f_invokeobj bilden einen Verschluss, und das g () -Funktionsobjekt und das g_invokeobj-f_invokeobj-Objektkette bildet den zweiten Verschluss. Wenn die G () -Funktion ausgeführt wird, da die G () -Funktion nicht mehr verwendet wird, wird der G () -Schulsabschluss gesammelt; Wenn dann die F () -Funktion ausgeführt wird, wird der F () -Schlosende aus dem gleichen Grund auch Müll gesammelt.
Aus der Definition des Verschlusses können wir eine Schlussfolgerung ziehen: Alle JavaScript -Funktionen sind Schließungen nach der Definition, da alle Funktionen Objekte sind und alle Funktionen auch ihre entsprechenden Anrufobjektketten nach der Ausführung haben.
Was jedoch die Schließungen wirklich funktioniert, ist der Fall von verschachtelten Funktionen. Da die eingebettete Funktion nur dann definiert ist, wenn die externe Funktion ausgeführt wird, ist der im Verschluss der eingebettete Funktion gespeicherte variable Wert (insbesondere der lokale variable Wert der externen Funktion) der Wert während dieses Laufs. Solange das eingebettete Funktionsobjekt noch existiert, besteht sein Schließ immer noch (der variable Wert in der Schließung ändert sich nicht), wodurch der Zweck des Speicherns der Informationen des Funktionsprozesses erreicht wird. Betrachten Sie das folgende Beispiel:
Die Codekopie lautet wie folgt:
var a = "draußen";
Funktion f () {
var a = "innen";
Funktion g () {return a;}
return g;
}
var result = f ();
console.log (result ()); // im Inneren
In diesem Beispiel wird die Funktion g () definiert, wenn die Funktion f () ausgeführt wird, und ein Verschluss der G () -Funktion erzeugt wird. Der G () -Clessur enthält die Objektkette G_Invokeobj-F_InvokeObj, sodass der Wert der Variablen A während der Funktion f () gespeichert wird. Wenn die Anweisung console.log () ausgeführt wird, existiert der G () -Clessur noch, da das G -Funktionsobjekt noch vorhanden ist. Beim Ausführen dieses noch bestehenden G-Funktionsobjekts verwendet JavaScript den noch bestehenden G () -Clessure und erhält den Wert der Variablen A ("innen").