Verschluss ist eine Schwierigkeit in der JavaScript -Sprache und ihrer Funktion. Viele fortgeschrittene Anwendungen stützen sich auf Schließungen, um die Implementierung zu implementieren. Ich bin seit langem dem Konzept der Schließungen ausgesetzt, aber ich war verwirrt und konnte nicht verstehen, was JavaScript -Schließungen sind und was sie nützlich sind. Heute habe ich im Internet einen Artikel über JavaScript -Schließungen (Original -Link) gesehen. Es wurde sehr gut erklärt. Jetzt habe ich vollständig verstanden, dass JavaScript -Schließungen eine magische Sache und der Zweck von Schließungen sind. Ich werde sie hier schreiben, um sie mit Ihnen zu teilen. Ich hoffe, dass Freunde, die JavaScript -Schließungen nicht verstehen, Schließungen verstehen können, nachdem sie sie gelesen haben! Der größte Teil des folgenden Inhalts stammt aus dem Originaltext. Ich habe einige Codekommentare, Operation -Renderings und eine kleine Änderung in den Originaltext hinzugefügt, um das einfache Verständnis zu erhalten!
1. Der Umfang der Variablen
Um Schließungen zu verstehen, müssen Sie zuerst den besonderen variablen Bereich von JavaScript verstehen.
In JavaScript ist der Variablenumfang in zwei Typen unterteilt: globale Variablen und lokale Variablen.
In JavaScript können globale Variablen direkt in eine Funktion gelesen werden.
var n =; // Definieren Sie die globale Variable nFunktion f () {alert ("Zugriff auf die globale Variable n, n ="+n); // Zugriff auf die globale Variable n} f (); //Auslaufergebnisse:
Umgekehrt ist jedoch nicht möglich. Lokale Variablen innerhalb der Funktion können nicht außerhalb der Funktion gelesen werden.
Funktion f () {var n =; // Definieren Sie die lokale Variable n} alert ("Zugriff auf die lokale Variable n außerhalb der Funktion, n ="+n); // Zugriff auf die lokale Variable n außerhalb der Funktion, Fehler: N ist nicht definiertAuslaufergebnisse:
Hier gibt es einen Platz zu beachten. Wenn Sie die Variablen intern deklarieren, müssen Sie den Befehl var verwenden. Wenn nicht, ist es tatsächlich eine globale Variable, die deklariert wurde!
Funktion f () {n =;} f (); alert ("n wird nicht mit Var in der F1 -Funktion deklariert, zu diesem Zeitpunkt ist n eine globale Variable, /r /n Beweis: n ="+n+", das Ergebnis des Fensters.n == n ist:"+(Fenster);Auslaufergebnisse:
2. Wie kann man lokale Variablen von außen lesen?
Aus verschiedenen Gründen müssen wir manchmal lokale Variablen innerhalb der Funktion erhalten. Wie bereits erwähnt, kann dies jedoch unter normalen Umständen nicht erfolgen und kann nur durch Problemumgehungen erreicht werden.
Das heißt, eine andere Funktion innerhalb der Funktion zu definieren.
Funktion f () {var n =; // Lokale Variable n In der F -Funktion // eine f -Funktion f () {// in der f -Funktion, alert (n); //}}Im obigen Code ist die Funktion F2 in Funktion F1 enthalten, und alle lokalen Variablen in F1 sind für F2 sichtbar. Aber umgekehrt ist nicht möglich. Lokale Variablen in F2 sind für F1 unsichtbar. Dies ist die "Chain Scope" -Struktur, die für die JavaScript -Sprache einzigartig ist. Die untergeordneten Objekte schauen für alle übergeordneten Objektvariablen auf der Ebene nach oben. Daher sind alle Variablen des übergeordneten Objekts für das untergeordnete Objekt sichtbar, sonst ist es nicht wahr. Da F2 lokale Variablen in F1 lesen kann, können wir seine internen Variablen außerhalb von F1 nicht lesen, solange F2 als Rückgabewert verwendet wird? Einige Leute können Fragen haben. F2 ist eine Funktion, wie kann es als Rückgabewert der F1 -Funktion zurückgegeben werden? Tatsächlich ist es in Ordnung. Der Funktionsname in JavaScript selbst ist eine Variable, sodass die Funktion auch als normale Variable verwendet werden kann. Das heißt, nicht nur eine Funktion kann an eine andere Funktion wie die Übergabeparameter übergeben werden, sondern eine Funktion kann auch als Rückgabewert einer anderen Funktion zurückgegeben werden.
Funktion f () {var n =; // Lokale Variable n // f Funktion in der f -Funktion f () {alert (n); } return f; // F -Funktion als Rückgabewert der F -Funktion} var result = f () verwenden; // Der Rückgabewert nach F -aufgerufen ist eine F -Funktion, und das Ergebnis ist F -Funktion Ergebnis (); // 999, rufen Sie F2 -Funktion aufAuslaufergebnisse:
3. Das Konzept der Schließung
Die F2 -Funktion im vorherigen Abschnitt des Code ist der Verschluss. Die Definition von "Schließung" in verschiedenen professionellen Dokumenten ist sehr abstrakt. Beispielsweise gibt es eine Verschlussdefinition: "Ein JavaScript -Verschluss ist eine Variable, die sie aus der vorherigen Funktion oder Umfang der vorherigen Ebene in einem anderen Bereich erhält, und diese Variablen werden nicht zerstört, wenn die Ausführung der vorherigen Ebene der vorherigen Ebene abgeschlossen ist." Es fällt mir schwer, eine solche Abschlussdefinition zu verstehen. Mein Verständnis ist, dass eine Schließung eine Funktion ist, die Variablen in anderen Funktionen lesen kann. Da in JavaScript -Sprache nur Unterfunktionen innerhalb von Funktionen lokale Variablen lesen können, können Schließungen einfach als "in einer Funktion definierte Funktionen" verstanden werden. Im Wesentlichen ist ein Verschluss eine Brücke, die das Innere und die Außenseite der Funktion verbindet.
4. Der Zweck der Schließung
Schließungen können an vielen Stellen verwendet werden. Es hat zwei größte Verwendungszwecke, eine ist, dass die Variablen in der Funktion wie oben erwähnt gelesen werden können, und das andere ist, dass die Werte dieser Variablen immer im Speicher gehalten werden.
Wie versteht man diesen Satz? Bitte beachten Sie den Code unten.
Funktion f () {var n =; // nadd ist eine globale Variable, die mit Var nicht deklariert wird. Diese Variable weist nun auf eine in der f -Funktion nadd = function () {n+=} Funktion f () {alert (n); } return f; } var result = f (); // Ergebnis ist das F -Funktion Ergebnis (); // Der erste Aufruf zur Ergebnisfunktion nadd (); // nadd repräsentiert eine anonyme Funktion, die in der F -Funktion festgelegt ist, nadd () ist das anonyme Funktion Ergebnis (); // der zweite Aufruf zur Ergebnisfunktion 1000 1000Auslaufergebnisse:
In diesem Code ist das Ergebnis tatsächlich die F2 -Funktion des Verschlusss. Insgesamt wird zweimal ausgeführt, der erste Wert beträgt 999 und der zweite Wert beträgt 1000. Dies zeigt, dass die lokale Variable N in der Funktion F1 im Speicher gehalten wurde und nach dem Aufrufen von F1 nicht automatisch gelöscht wird.
Warum passiert das? Der Grund dafür ist, dass F1 die übergeordnete Funktion von F2 ist und F2 einer globalen Variablen zugeordnet ist, die dazu führt, dass F2 immer im Gedächtnis ist, und die Existenz von F2 hängt von F1 ab. Daher ist F1 immer im Gedächtnis und wird nach Abschluss des Anrufs nicht vom Müllsammlungsmechanismus recycelt.
Ein weiterer bemerkenswerter Punkt in diesem Code ist, dass die Zeile "nadd = function () {n+= 1}" zuerst vor NADD verwendet wird, sodass NADD eine globale Variable ist, keine lokale Variable. Zweitens ist der Wert von NADD eine anonyme Funktion, und diese anonyme Funktion selbst ist ebenfalls ein Verschluss, sodass NADD einem Setter entspricht, der auf lokalen Variablen innerhalb der Funktion außerhalb der Funktion arbeiten kann.
5. Hinweise zur Verwendung von Schließungen
1) Da Verschlüsse dazu führen, dass alle Variablen in der Funktion im Speicher gespeichert werden und der Speicherverbrauch sehr groß ist, können Verschlüsse nicht missbraucht werden, andernfalls verursacht dies Leistungsprobleme auf der Webseite und kann zu einem Speicherleck der IE führen. Die Lösung besteht darin, alle lokalen Variablen zu löschen, die vor dem Verlassen der Funktion nicht verwendet werden.
2) Der Verschluss ändert den Wert der Variablen innerhalb der übergeordneten Funktion außerhalb der übergeordneten Funktion. Wenn Sie die übergeordnete Funktion als Objekt verwenden, verwenden Sie den Verschluss als öffentliche Methode und die interne Variable als private Eigenschaft, achten Sie darauf, den Wert der internen Variablen der übergeordneten Funktion nicht nach Belieben zu ändern.
6. Fragen denken
Wenn Sie die laufenden Ergebnisse der folgenden zwei Code -Teile verstehen können, sollten Sie als Verständnis des laufenden Mechanismus des Verschlusses in Betracht gezogen werden.
Code -Snippet 1:
var name = "das Fenster"; var Object = {Name: "Mein Objekt", getNameFunc: function () {return function () {return this.name; }; }}; alert (Object.getNameFunc () () ());Auslaufergebnisse:
Code -Snippet zwei:
var name = "das Fenster"; var Object = {Name: "Mein Objekt", getNameFunc: function () {var that = this; return function () {return that.name; }; }}; alert (Object.getNameFunc () ());Auslaufergebnisse:
Die folgenden Kommentare werden dem Code hinzugefügt, um die laufenden Ergebnisse der beiden oben genannten Code -Snippets zu analysieren:
Code -Snippet 1:
Die Analyse ist wie folgt:
/*In JavaScript werden die von uns erklarenden JavaScript -globalen Objekte, globalen Funktionen und globalen Variablen automatisch Mitglieder des Fensterobjekts. Globale Variablen sind Eigenschaften von Fensterobjekten. Globale Funktionen sind Methoden von Fensterobjekten. */var name = "Das Fenster"; // einen globalen Variablennamen deklarieren, und zu diesem Zeitpunkt wird der globale Variable -Name automatisch zu einem Attribut des Fensterobjekts // Beweis: alert ("Fenster.Name:"+Fenster.name); // Sie können auf den Namen in Form des Fensters zugreifen. Zeit Das globale Variablenobjekt Objekt wird automatisch zu einem Attribut des Fensterobjekts var Object = {Name: "Mein Objekt", // Attributname des Objekts getNameFunc: function () {// GetNameFunc -Funktion des Objektobjekts von Objektobjekt // Rückgabewert der GetNameFunc -Methode des Objekts Objekt. zu welchem Objekt. // beweisen, dass dies in der anonymen Funktion ein Fensterobjekt anstelle eines ObjektAlert darstellt ("this == -Objektergebnis lautet:"+(this == -Objekt)); alert ("this == Fenster ist:"+(this == Fenster)); Geben Sie dies zurück. NAME; // Da dies ein Fensterobjekt darstellt, greift dies auf natürlich auf den Namen des Fensterobjekts "Das Fenster"} zu. }}; // Beweis: Das globale Objektobjekt ist ein Attribut des Fensterobjekts Alert ("window.Object:"+window.object); alert ("window.object.name:"+window.object.name);/*Nach dem Aufrufen der GetNameFunc -Methode wird eine anonyme Methode zurückgegeben. Zu diesem Zeitpunkt stellt RETFN eine anonyme Methode dar. Jetzt ist es gleichwertig, der anonymen Methode einen Namen zu geben. Zu diesem Zeitpunkt wird die RETFN -Funktion automatisch zu einer Funktion des Fensterobjekts*/var retfn = Object.getNameFunc (); alert (retfn ()); // Aufrufen der zurückgegebenen anonymen Methode, wer nennt diese anonyme Methode also? Es handelt sich um ein Fensterobjekt // Beweis: Die RETFN -Funktion ist eine Funktion der Fensterobjekt -Warnung ("window.retfn ():"+window.retfn ()); // Sie können die RETFN -Methode in Form von window.retfn () (Objektname.Code -Snippet zwei:
Die Analyse ist wie folgt:
var name = "Das Fenster"; // Global Variable Name // Global Object ObjectVar Object = {Name: "Mein Objekt", getNameFunc: function () {/*Welches Objekt repräsentiert dies dies zu diesem Zeitpunkt? Dies repräsentiert das Objektobjekt. Welches Objekt nennt die Funktion, in der sich dies befindet? Dies bezieht sich darauf, welches Objekt ausgeführt wurde, dies = dies, und das repräsentiert auch das Objektobjekt*/var, dass = this; // eine lokale Variable ist, die in der Funktion getNameFunc für GetNamefunc deklariert ist. alert ("this == Fenster ist:"+(this == Fenster)); // Beweisen Sie, dass das Objekt -Objekt -Alert ("that == Object -Ergebnis ist:"+(that == Objekt)); return function () {/*dh eine lokale Variable, die in der GetNameFunc -Funktion deklariert ist. Unter normalen Umständen, nachdem der Funktion "GetNamefunc -Funktion" abgeschlossen ist, wird die lokale Variable, die von JavaScripts GC recycelt wird, und befreien den Speicherplatz, der von der lokalen Variablen besetzt ist, die jedoch jetzt normal verwendet werden kann und nicht recycelt wurde. Der Grund dafür ist, dass GetNameFunc die übergeordnete Funktion der anonymen Funktion ist. Nachdem die Funktion getNameFunc aufgerufen wurde, wird die anonyme Funktion zurückgegeben und einer globalen Variablen -RETFN zugeordnet, die dazu führt, dass die anonyme Funktion immer im Speicher ist, und die Existenz der anonymen Funktion hängt von der GetNamefunc -Funktion ab. Daher befindet sich die GetNamefunc -Funktion immer im Speicher und wird nach Abschluss des Anrufs nicht vom Müllsammlungsmechanismus recycelt. Da sich die GetNameFunc -Funktion immer im Speicher befindet, existiert die in der GetNameFunc -Funktion deklarierte lokale Variable immer im Speicher. Da es existiert, kann es natürlich weiterhin verwendet werden. */return that.name; // Das repräsentiert das Objektobjekt, so dass der Name auf natürliche Weise auf den Objektnamen "mein Objekt"} zugreift; }}; var retfn = Object.getNameFunc (); // Nach dem Aufrufen der GetNameFunc -Methode wird eine anonyme Methode zurückgegeben. Zu diesem Zeitpunkt repräsentiert RETFN eine anonyme Methode, die nun der anonymen Methode entspricht. Ein Name ist RETFN -Alarm (RETFN ());Schließlich habe ich auch ein Beispiel beigefügt, das ich geschrieben habe, als ich zuvor JavaScript -Schließungen lernte:
<script type = "text/javaScript"> Funktion a () {var i =; // Deklare die lokale Variable I Innenfunktion A/deklarieren Sie die Subfunktion Bfunction b () {alert ("i ="+(++ i)); // Zugriff auf die lokale Variable Ich deklarierte innerhalb der Funktion a} zurück. zeigt auf die Funktion b. B. Die Variable I wird verwendet. Nach der Ausführung von C () wird ein Fenster angezeigt, um den Wert von I (das erste Mal) anzuzeigen, und dieser Code schafft tatsächlich einen Schließ, da die Variable C außerhalb der Funktion A auf die Funktion B innerhalb der Funktion A bezieht. Das heißt: Wenn die interne Funktion b der Funktion a durch eine Variable außerhalb der Funktion A referenziert wird, wird ein sogenannter "Verschluss" -Cessur erzeugt. Nachdem A ausgeführt und zurückgegeben wurde, wird der Verschluss den Mechanismus des JavaScript -Müllsammers GC nicht recyceln, da die Ressourcen von A besetzt sind, da die Ausführung der internen Funktion b der Variablen in einem */a (); // es definitiv Speicherplatz im Speicher gibt. Nach einer () ausgeführten () wird GC den für i var c = a () zugewiesenen Speicherraum recyceln. GC behandelt I nicht als Müll und c (); // Äquivalent zu b ().Auslaufergebnisse:
Der obige Inhalt ist die detaillierte Erläuterung des vom Editors vorgestellten JavaScript -Wissenspunkte (16), der den Code für JavaScript Closure (Closeure) der JavaScript -Wissenspunkte (16) zusammengestellt hat. Ich hoffe, es wird für alle hilfreich sein!