Ausführliche Erklärung der Closure in JavaScript

Ausführliche Erklärung der Closure in JavaScript

Einführung

Closure ist eine sehr leistungsstarke Funktion in JavaScript. Der sogenannte Closure ist eine Funktion innerhalb einer Funktion. Die innere Funktion kann auf den Gültigkeitsbereich der äußeren Funktion zugreifen, sodass Closures für leistungsstärkere Aufgaben verwendet werden können.

Heute werde ich euch eine ausführliche Einführung zum Thema Closures geben.

Funktionen innerhalb von Funktionen

Wir haben erwähnt, dass Funktionen innerhalb von Funktionen auf Variablen im übergeordneten Funktionsumfang zugreifen können. Sehen wir uns ein Beispiel an:

Funktion übergeordneteFunktion() {
 var Adresse = "flydean.com"; 
 Funktion Alarmadresse() { 
 Alarm (Adresse); 
 }
 Alarmadresse();
}
übergeordneteFunktion();

Im obigen Beispiel definieren wir eine Variablenadresse in der übergeordneten Funktion, definieren eine Methode „alertAddress“ innerhalb der übergeordneten Funktion und greifen innerhalb dieser Methode auf die in der externen Funktion definierte Adressvariable zu.

Beim Ausführen des obigen Codes treten keine Probleme auf und auf die Daten kann korrekt zugegriffen werden.

Schließung

Da wir nun über Funktionen innerhalb von Funktionen verfügen, stellt sich die Frage, was Closures sind.

Schauen wir uns das folgende Beispiel an:

Funktion übergeordneteFunktion() {
 var Adresse = "flydean.com"; 
 Funktion Alarmadresse() { 
 Alarm (Adresse); 
 }
 Alarmadresse zurückgeben;
}
var meineFunktion = übergeordneteFunktion();
meineFunktion();

Dieses Beispiel ist dem ersten Beispiel sehr ähnlich, außer dass wir die innere Funktion zurückgeben und sie myFunc zuweisen.

Als nächstes haben wir myFunc direkt aufgerufen.

MyFunc greift auf die Adressvariable in parentFunction zu, obwohl parentFunction die Ausführung bereits abgeschlossen und zurückgekehrt ist.

Aber wenn wir myFunc aufrufen, können wir immer noch auf die Adressvariable zugreifen. Das ist ein Abschluss.

Diese Funktion des Closure ist sehr nützlich. Wir können Closure verwenden, um eine Funktionsfabrik zu generieren, wie unten gezeigt:

Funktion makeAdder(x) {
 Rückgabefunktion (y) {
 gib x + y zurück;
 };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2)); // 7
console.log(add10(2)); // 12

Add5 und add10 sind beides Closures, die von der Funktionsfabrik makeAdder erstellt werden. Durch die Übergabe unterschiedlicher x-Parameter erhalten wir unterschiedliche Basen der Add-Methode.

Schließlich werden zwei verschiedene Add-Methoden generiert.

Mithilfe des Konzepts der Funktionsfabrik können wir eine praktische Anwendung von Closure betrachten. Beispielsweise haben wir drei Schaltflächen auf der Seite und indem wir auf diese Schaltflächen klicken, können wir die Schriftart ändern.

Wir können zunächst drei Methoden über die Funktionsfabrik generieren:

Funktion makeSizer(Größe) {
 return Funktion() {
 document.body.style.fontSize = Größe + 'px';
 };
}

var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);

Mit diesen drei Methoden binden wir das DOM-Element an die Callback-Methode:

document.getElementById('size-12').onclick = size12;
document.getElementById('size-14').onclick = size14;
document.getElementById('size-16').onclick = size16;

Verwenden von Closures zum Implementieren privater Methoden

Im Vergleich zu Java verfügt Java über private Zugriffsdeskriptoren. Durch privat können wir angeben, dass auf die Methode nur innerhalb der Klasse zugegriffen werden kann.

So etwas gibt es in JS natürlich nicht, aber wir können Closures verwenden, um denselben Effekt zu erzielen.

var Zähler = (Funktion() {
 var privateCounter = 0;
 Funktion changeBy(val) {
 privaterZähler += Wert;
 }

 zurückkehren {
 Inkrement: Funktion() {
  ändernDurch(1);
 },

 Dekrement: Funktion() {
  ändernDurch(-1);
 },

 Wert: Funktion() {
  gib privatenZähler zurück;
 }
 };
})();

konsole.log(Zähler.Wert()); // 0.

Zähler.Inkrement();
Zähler.Inkrement();
konsole.log(zähler.wert()); // 2.

Zähler.Dekrement();
konsole.log(zähler.wert()); // 1.

Wir haben die Eigenschaft „privateCounter“ und die Methode „changeBy“ in der übergeordneten Funktion definiert, auf diese Methoden kann jedoch nur in der internen Funktion zugegriffen werden.

Wir verwenden das Konzept der Schließung, um diese Eigenschaften und Methoden zu kapseln und sie der externen Verwendung zugänglich zu machen, wodurch letztendlich der Effekt der Kapselung privater Variablen und Methoden erzielt wird.

Umfang der Abschlüsse

Für jeden Abschluss gibt es einen Gültigkeitsbereich, einschließlich des Gültigkeitsbereichs der Funktion selbst, des Gültigkeitsbereichs der übergeordneten Funktion und des globalen Gültigkeitsbereichs.

Wenn wir eine neue Funktion in eine Funktion einbetten, wird eine Bereichskette gebildet, die wir als Scope-Chain bezeichnen.

Schauen Sie sich unten ein Beispiel an:

// globaler Geltungsbereich
var e = 10;
Funktion Summe(a){
 Rückgabefunktion (b) {
 Rückgabefunktion (c) {
  // Umfang der äußeren Funktionen
  Rückgabefunktion (d) {
  // lokaler Geltungsbereich
  gib a + b + c + d + e zurück;
  }
 }
 }
}

console.log(Summe(1)(2)(3)(4)); // log 20

Häufige Probleme mit Verschlüssen

Das erste häufige Problem ist die Verwendung von Closures bei der Schleifendurchquerung. Sehen wir uns ein Beispiel an:

Funktion zeigeHilfe(Hilfe) {
 document.getElementById('Hilfe').innerHTML = Hilfe;
}

Funktion setupHelp() {
 var Hilfetext = [
  {'id': 'email', 'help': 'Ihre E-Mail-Adresse'},
  {'id': 'name', 'help': 'Ihr vollständiger Name'},
  {'id': 'Alter', 'Hilfe': 'Ihr Alter (Sie müssen über 16 sein)'}
 ];

 für (var i = 0; i < Hilfetext.Länge; i++) {
 var item = Hilfetext[i];
 Dokument.getElementById(item.id).onfocus = Funktion() {
  Hilfe anzeigen(item.help);
 }
 }
}

setupHilfe();

Im obigen Beispiel haben wir eine setupHelp-Funktion erstellt. In setupHelp wird der onfocus-Methode ein Closure zugewiesen, sodass das Element im Closure auf die in der externen Funktion definierte Elementvariable zugreifen kann.

Da wir Werte innerhalb einer Schleife zuweisen, erstellen wir tatsächlich drei Abschlüsse, aber diese drei Abschlüsse teilen sich den gleichen Umfang der äußeren Funktion.

Unsere Absicht ist, dass unterschiedliche IDs unterschiedliche Hilfemeldungen auslösen. Aber wenn wir es tatsächlich ausführen, werden wir feststellen, dass die endgültige Nachricht die letzte ist, unabhängig von der ID.

Da onfocus erst nach dem Erstellen des Abschlusses ausgelöst wird, ändert sich der Wert von item tatsächlich zu diesem Zeitpunkt. Nach dem Ende der Schleife hat der Wert von item auf das letzte Element gezeigt, sodass nur die Hilfemeldung der letzten Daten angezeigt wird.

Wie kann dieses Problem gelöst werden?

Am einfachsten ist es, den in ES6 eingeführten let-Deskriptor zu verwenden, um das Element als Bereich des Blocks zu definieren. Bei jeder Ausführung der Schleife wird ein neues Element erstellt, sodass der Wert des Elements im Abschluss unverändert bleibt.

 für (lass i = 0; i < Hilfetext.Länge; i++) {
 let item = Hilfetext[i];
 Dokument.getElementById(item.id).onfocus = Funktion() {
  Hilfe anzeigen(item.help);
 }
 }

Eine andere Möglichkeit besteht darin, einen weiteren Abschluss zu erstellen:

Funktion makeHelpCallback(Hilfe) {
 return Funktion() {
 Hilfe anzeigen(Hilfe);
 };
}

 für (var i = 0; i < Hilfetext.Länge; i++) {
 var item = Hilfetext[i];
 document.getElementById(item.id).onfocus = makeHelpCallback(item.help);
 }

Hier wird das zuvor erwähnte Konzept der Funktionsfabrik verwendet und wir erstellen unterschiedliche Bereichsumgebungen für unterschiedliche Abschlüsse.

Eine andere Möglichkeit besteht darin, das Element in einen neuen Funktionsumfang aufzunehmen, sodass bei jeder Erstellung ein neues Element entsteht, was dem Prinzip von let ähnelt:

 für (var i = 0; i < Hilfetext.Länge; i++) {
  (Funktion() {
    var item = Hilfetext[i];
    Dokument.getElementById(item.id).onfocus = Funktion() {
     Hilfe anzeigen(item.help);
    }
  })(); 
 }

Das zweite häufige Problem sind Speicherlecks.

 Funktion übergeordnete Funktion (paramA)
 {
 var a = paramA;
 Funktion childFunction()
 {
 gib a + 2 zurück;
 }
 gibt untergeordnete Funktion zurück();
 }

Im obigen Beispiel bezieht sich childFunction auf die Variable a von parentFunction. Solange die ChildFunction noch verwendet wird, kann sie nicht freigegeben werden, was zur Folge hat, dass die ParentFunction nicht durch die Speicherbereinigung gelöscht werden kann.

Probleme mit der Schließleistung

Wir definieren ein Objekt und greifen über eine Closure auf seine privaten Eigenschaften zu:

Funktion MeinObjekt(Name, Nachricht) {
 dieser.name = name.toString();
 diese.Nachricht = Nachricht.toString();
 dies.getName = Funktion() {
  gib diesen Namen zurück;
 };

 diese.getMessage = Funktion() {
  gib diese Nachricht zurück;
 };
}

Was ist mit dem obigen Objekt nicht in Ordnung?

Das Problem bei obigem Objekt besteht darin, dass bei jedem neuen Objekt die Methoden getName und getMessage kopiert werden, was einerseits zu inhaltlicher Redundanz führt und andererseits die Performance beeinträchtigt.

Im Allgemeinen definieren wir die Methoden des Objekts am Prototyp:

Funktion MeinObjekt(Name, Nachricht) {
 dieser.name = name.toString();
 diese.Nachricht = Nachricht.toString();
}
MeinObjekt.prototype.getName = Funktion() {
 gib diesen Namen zurück;
};
MeinObjekt.prototype.getMessage = Funktion() {
 gib diese Nachricht zurück;
};

Beachten Sie, dass wir den gesamten Prototyp nicht direkt neu schreiben sollten, da dies zu unbekannten Fehlern führen würde. Wir müssen nur bei Bedarf bestimmte Methoden neu schreiben.

Zusammenfassen

Closures sind ein sehr leistungsfähiges und nützliches Konzept in JS. Ich hoffe, sie gefallen Ihnen.

Dies ist das Ende dieses Artikels über Closure in JavaScript. Weitere relevante Inhalte zu Closure in JavaScript finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den verwandten Artikeln weiter unten. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Erfahren Sie mehr über Javascript-Closures
  • Zusammenfassung der JavaScript-Wissenspunkte (XVI) Detaillierte Erläuterung des Javascript-Closure-Codes
  • Closures in der funktionalen Programmierung in JavaScript verstehen
  • Detaillierte Erklärung der Schließung in Javascript
  • Eine kurze Analyse der Anwendungsbeispiele von Javascript-Closures
  • Javascript-Abschlüsse
  • Details zum JavaScript-Abschluss

<<:  Grafisches Tutorial zur Installation und Konfiguration von MySQL (CentOS7)

>>:  MySQL 5.7-Installation Der MySQL-Dienst kann nicht gestartet werden, meldet jedoch keine Fehler

Artikel empfehlen

Kapselungsmethode der Vue-Breadcrumbs-Komponente

Vue kapselt die Breadcrumb-Komponente zu Ihrer In...

Detailliertes Installations- und Deinstallationstutorial für MySQL 8.0.12

1. Installationsschritte für MySQL-Version 8.0.12...

Die normale Methode der MySQL-Deadlock-Prüfungsverarbeitung

Normalerweise wird bei einem Deadlock die Verbind...

Vue+Websocket implementiert einfach die Chat-Funktion

In diesem Artikel wird der spezifische Code von V...

Tipps zur Verwendung des Befehls „Docker Inspect“

Beschreibung und Einführung Docker Inspect ist ei...

Analyse der Verwendung der Funktion zur sofortigen Ausführung in JavaScript

Wir wissen, dass eine Funktion im Allgemeinen auf...

Detaillierte Erläuterung der dauerhaften Speicherung von Redis unter Docker

In diesem Kapitel beginnen wir mit dem Betrieb vo...

So reduzieren Sie den Speicherverbrauch und die CPU-Auslastung von Webseiten

Manche Webseiten erscheinen möglicherweise nicht ...

Zusammenfassung der MySQL-Injection-Bypass-Filtertechniken

Schauen wir uns zunächst den GIF-Vorgang an: Fall...

Vue+el-table realisiert das Zusammenführen von Zellen

In diesem Artikelbeispiel wird der spezifische Co...

So verwenden Sie Filter zur Implementierung der Überwachung in Zabbix

Als ich kürzlich an Überwachungsgeräten arbeitete...