Detaillierte Erklärung des Prinzips und der Funktion des JavaScript-Closures

Detaillierte Erklärung des Prinzips und der Funktion des JavaScript-Closures

Einführung

veranschaulichen

Dieser Artikel stellt die Rolle, den Zweck und das Prinzip von JavaScript-Closures vor.

Definition von „Closure“

Abschluss bedeutet, dass die innere Funktion immer auf die in der äußeren Funktion deklarierten Variablen und Parameter zugreifen kann, auch in der äußeren Funktion.

Nach Rückgabe der Nummer (Lebensdauer abgelaufen).

Die Rolle (Eigenschaften) von Verschlüssen

1. Funktionen innerhalb von Funktionen

2. Interne Funktionen können auf Parameter oder Variablen externer Funktionen verweisen

3. Für die Parameter und Variablen der externen Funktion erfolgt keine Speicherbereinigung, da sie von der internen Funktion referenziert werden.

Closures und globale Variablen

Verwendung von Verschlüssen

Curryen

Über Parameter können verschiedene Funktionen generiert werden.

Funktion makeWelcome(x) {
	Rückgabefunktion (y) {
		gib x + y zurück;
	};
}
 
sagen wir „Hallo“ = „Willkommen heißen“ („Hallo,“);
sagen wir „Hi“ = „Welcome("Hi,");
 
console.log(sagHallo("Tony"));
console.log(sagHallo("Tony"));

Ergebnis

Hallo Tony

Hallo, Tony

Implementieren öffentlicher Variablen

Anforderung: Implementieren Sie einen Akkumulator, der sich bei jedem Aufruf um eins erhöht.

Funktion makeCounter(){
	lass count = 0;
	Funktion innereFunktion(){
		Anzahl zurückgeben++;
	}
	innere Funktion zurückgeben;
}
Lassen Sie Zähler = makeCounter();
 
console.log(Zähler());
console.log(Zähler());
console.log(Zähler());

Ergebnis

0

1

2

Cache

Stellen Sie sich vor, es gibt ein Funktionsobjekt, dessen Verarbeitung sehr zeitaufwändig ist. Der berechnete Wert kann gespeichert werden. Wenn diese Funktion aufgerufen wird, wird zuerst im Cache danach gesucht. Wird dieser nicht gefunden, wird er berechnet, anschließend der Cache aktualisiert und der Wert zurückgegeben, wird er gefunden, wird der gefundene Wert direkt zurückgegeben.

Dies ist bei Closures möglich, da sie keine externen Referenzen freigeben und der Wert innerhalb der Funktion somit erhalten bleibt.

Der Einfachheit halber wird in diesem Artikel direkt ein Beispiel für einen Lese-/Schreib-Cache beschrieben. (Anstatt es zu berechnen, wenn es nicht gelesen werden kann, und es dann im Cache zu speichern).

let cache = funktion () {
	// Map erlaubt Schlüssel jeden Typs. Wenn Sie schreiben: let storage = {}, kann der Schlüssel nur eine Zeichenfolge sein: let storage = new Map();
	zurückkehren {
		setCache: Funktion (k, v) {
			Speicher[k] = v;
		},
		getCache: Funktion (k) {
			Rückgabespeicher[k];
		},
		deleteCache: Funktion (k) {
			Speicher löschen[k];
		}
	}
}();
 
cache.setCache('a', 1);
Konsole.log(Cache.getCache('a'))

Ergebnis

1

Kapselung (Privatisierung von Attributen)

Auf interne Variablen kann nur über den bereitgestellten Abschluss zugegriffen werden. (Diese Methode ist nicht gut, es wird empfohlen, die Prototypkette zu verwenden).

lass Person = Funktion(){
	//Der Variablenbereich liegt innerhalb der Funktion und kann von außen nicht aufgerufen werden let name = "defaultName";
 
	zurückkehren {
		getName: Funktion(){
			Rückgabename;
		},
		setName: Funktion(neuerName){
			Name = neuerName;
		}
	}
}();
 
Konsole.log(Person.Name);
console.log(person.getName());
person.setName("Hallo");
console.log(person.getName());

Ergebnis

undefiniert

Standardname

Hallo

Das Prinzip der Schließung

Nehmen wir den Zähler als Beispiel:

Funktion makeCounter() {
	lass count = 0;
	return Funktion() {
		Anzahl zurückgeben++;
	};
}
lass Zähler = makeCounter();
console.log(Zähler());
console.log(Zähler());
console.log(Zähler());

Ergebnis

0

1

2

Zu Beginn jedes makeCounter()-Aufrufs wird ein neues LexicalEnvironment-Objekt erstellt, um die Variablen für diese makeCounter-Laufzeit zu speichern.

Daher gibt es zwei Ebenen verschachtelter lexikalischer Umgebungen:

Die Ausführung von makeCounter() erstellt eine verschachtelte Funktion, die nur eine Zeile einnimmt: return count++ . Wir haben es noch nicht ausgeführt, wir haben es nur erstellt.

Alle Funktionen merken sich die lexikalische Umgebung, in der sie bei ihrer „Geburt“ erstellt wurden. Begründung: Alle Funktionen haben ein verstecktes Attribut namens [[Umgebung]], das einen Verweis auf die lexikalische Umgebung enthält, in der die Funktion erstellt wurde:

Daher verfügt counter.[[Environment]] über einen Verweis auf die lexikalische Umgebung {count: 0}. Auf diese Weise merkt sich eine Funktion, wo sie erstellt wurde, unabhängig davon, wo die Funktion aufgerufen wird. Die [[Umgebung]]-Referenz wird beim Erstellen der Funktion festgelegt und dauerhaft gespeichert.

Später, wenn counter() aufgerufen wird, wird für diesen Aufruf eine neue lexikalische Umgebung erstellt und deren äußere Referenz auf die lexikalische Umgebung wird von counter.[[Umgebung]] abgerufen :

Wenn der Code in counter() nun nach der Zählvariable sucht, durchsucht er zuerst seine eigene lexikalische Umgebung (die leer ist, da dort keine lokalen Variablen vorhanden sind), dann die lexikalische Umgebung des äußeren makeCounter() und fixiert die Zählvariable, wo immer er sie findet.

Ändern (aktualisieren Sie die Variable in der lexikalischen Umgebung, in der die Variable vorhanden ist).

Dies ist der Status nach der Ausführung:

Wenn wir counter() mehrmals aufrufen, erhöht sich die Zählvariable an derselben Position auf 2, 3 usw.

Speicherbereinigung

Einführung

Normalerweise werden nach Abschluss eines Funktionsaufrufs die lexikalische Umgebung und alle darin enthaltenen Variablen aus dem Speicher gelöscht, da keine Verweise mehr darauf vorhanden sind.

Wie jedes andere Objekt in JavaScript bleibt eine lexikalische Umgebung nur so lange im Speicher, wie sie erreichbar ist. Wenn es jedoch eine verschachtelte Funktion gibt, die auch nach Beendigung der Funktion noch erreichbar ist, verfügt sie über ein [[Umgebung]]-Attribut, das auf die lexikalische Umgebung verweist.

Wenn die lexikalische Umgebung nach Abschluss der Funktion noch erreichbar ist, bleibt die verschachtelte Funktion wirksam. Zum Beispiel:

Funktion f() {
    sei Wert = 123;
    return Funktion() {
        Alarm(Wert);
    }
}
// g.[[Environment]] speichert einen Verweis auf die lexikalische Umgebung des entsprechenden f()-Aufrufs let g = f();

Wenn f() mehrmals aufgerufen wird und die zurückgegebene Funktion gespeichert wird, bleiben auch alle entsprechenden LexicalEnvironment-Objekte im Speicher erhalten. Zum Beispiel:

Funktion f() {
    lass Wert = Math.random();
    Rückgabefunktion () {
        Alarm(Wert);
    };
}
 
// 3 Funktionen in einem Array, jede mit der lexikalischen Umgebung des entsprechenden f() verknüpft. let arr = [f(), f(), f()];

Wenn ein LexicalEnvironment-Objekt nicht mehr erreichbar ist, stirbt es (wie jedes andere Objekt auch). Mit anderen Worten: Es existiert nur, solange mindestens eine verschachtelte Funktion darauf verweist.

Wenn im folgenden Code die verschachtelte Funktion gelöscht wird, wird auch die sie umgebende lexikalische Umgebung (und der darin enthaltene Wert) aus dem Speicher gelöscht:

Funktion f() {
    sei Wert = 123;
    return Funktion() {
        Alarm(Wert);
    }
} 
let g = f(); // Solange die g-Funktion existiert, bleibt der Wert im Speicher g = null; // Jetzt wird der Speicher bereinigt

Optimierung in der Ist-Entwicklung

Wie wir gesehen haben, existieren theoretisch auch alle Variablen außerhalb einer Funktion, wenn diese erreichbar ist. Aber in Wirklichkeit versuchen JavaScript-Engines, es zu optimieren. Sie analysieren die Variablenverwendung und wenn aus dem Code klar hervorgeht, dass unbenutzte externe Variablen vorhanden sind, werden diese entfernt.

Ein wichtiger Nebeneffekt hiervon in V8 (Chrome, Opera) ist, dass solche Variablen beim Debuggen nicht verfügbar sind.

Öffnen Sie die Entwicklertools des Chrome-Browsers und versuchen Sie, den folgenden Code auszuführen.

    Funktion f() {
        lass Wert = Math.random();
        Funktion g() {
            Debugger;
        }
        g zurückgeben;
    } 
    sei g = f();
    G();

Wenn der Code bis zur Stelle „debugger;“ ausgeführt wird, wird er angehalten. Geben Sie zu diesem Zeitpunkt console.log(value); in die Konsole ein.

Ergebnis: Fehler: VM146:1 Uncaught ReferenceError: Wert ist nicht definiert

Dies kann zu interessanten Debugging-Problemen führen. Beispielsweise können wir anstelle der erwarteten Variable eine externe Variable mit demselben Namen sehen:

let value = "Überraschung!";
Funktion f() {
    let value = "der nächste Wert";
    Funktion g() {
        Debugger;
    }
    g zurückgeben;
}
sei g = f();
G();

Wenn der Code bis zur Stelle „debugger;“ ausgeführt wird, wird er angehalten. Geben Sie zu diesem Zeitpunkt console.log(value); in die Konsole ein.

Ergebnis: Ausgabe: Überraschung.

Oben finden Sie ausführliche Informationen zum Prinzip und zur Funktion des JavaScript-Closures. Weitere Informationen zum JavaScript-Closure finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Lassen Sie uns ausführlich über die Rolle von Closures in JS sprechen
  • Erweiterte Closures in JavaScript erklärt
  • Details zum JavaScript-Abschluss
  • JavaScript-Closures erklärt
  • Lassen Sie uns lernen, was Javascript-Closures sind

<<:  Vier völlig unterschiedliche Erfahrungen im Interaktionsdesign der Apple Watch enthüllt

>>:  Detaillierte Erklärung des Integer-Datentyps tinyint in MySQL

Artikel empfehlen

33 der besten kostenlosen englischen Schriftarten geteilt

ChunkFive Freie Schriftfamilie Cuprum JAH I Kosten...

So optimieren Sie die MySQL-Abfragegeschwindigkeit

In den vorherigen Kapiteln haben wir die Auswahl ...

Einrichten von VMware vSphere in VMware Workstation (Grafisches Tutorial)

VMware vSphere ist die branchenführende und zuver...

MySQL Infobright-Installationsschritte

Inhaltsverzeichnis 1. Verwenden Sie den Befehl „r...

Beispielanalyse von MySQL-Start- und Verbindungsmethoden

Inhaltsverzeichnis So starten Sie mysqld Methode ...

CocosCreator - modulares Lernskript

Modulares Cocos Creator-Skript Mit Cocos Creator ...

Erstellen Sie eine Bildschirmaufzeichnungsfunktion mit JS

OBS studio ist cool, aber JavaScript ist cooler. ...

JS implementiert Städtelisteneffekt basierend auf VUE-Komponente

In diesem Artikelbeispiel wird der spezifische Co...

Methode zum Erstellen eines Redis-Clusters basierend auf Docker

Laden Sie das Redis-Image herunter Docker-Pull yy...

Vite+Electron zum schnellen Erstellen von VUE3-Desktopanwendungen

Inhaltsverzeichnis 1. Einleitung 2. Erstellen Sie...