7619 Stimmen

Wie funktionieren die JavaScript-Schließungen?

Wie würden Sie JavaScript-Schließungen jemandem erklären, der zwar die Konzepte kennt, aus denen sie bestehen (z. B. Funktionen, Variablen und Ähnliches), aber die Schließungen selbst nicht versteht?

Ich habe gesehen das Beispiel Schema auf Wikipedia angegeben, aber leider hat es nicht geholfen.

22voto

Shivprasad Koirala Punkte 25296

Diese Antwort ist eine Zusammenfassung dieses Youtube-Videos Javascript-Schließungen . Also volle Anerkennung für dieses Video.

Closures sind nichts anderes als Stateful-Funktionen, die den Zustand ihrer privaten Variablen beibehalten.

Normalerweise rufen Sie eine Funktion auf, wie in der folgenden Abbildung gezeigt. Die Variablen werden auf einem Stack (laufender RAM-Speicher) erstellt, verwendet und dann wieder freigegeben.

enter image description here

Aber jetzt gibt es Situationen, in denen wir diesen Zustand der Funktion beibehalten wollen, dass ist, wo Javascript Schließungen zum Einsatz kommt. Ein Closure ist eine Funktion innerhalb einer Funktion mit einem Rückruf, wie im folgenden Code gezeigt.

enter image description here

Der Schließungscode für die obige Zählerfunktion sieht also etwa so aus wie unten dargestellt: eine Funktion innerhalb einer Funktion mit einer Rückgabeanweisung.

function Counter() {
           var counter = 0;

           var Increment = function () {
               counter++;
               alert(counter);
           }
           return {
               Increment
           }
       }

Wenn Sie nun einen Aufruf tätigen, wird der Zähler erhöht, d. h. der Funktionsaufruf behält den Status bei.

var x = Counter(); // get the reference of the closure
x.Increment(); // Displays 1
x.Increment(); // Display 2 ( Maintains the private variables)

Nun stellt sich aber die große Frage nach dem Nutzen einer solchen zustandsabhängigen Funktion. Zustandsabhängige Funktionen sind Bausteine zur Implementierung von OOP-Konzepten wie Abstraktion, Kapselung und Erstellung von eigenständigen Modulen.

Was immer Sie also gekapselt haben wollen, können Sie als privat kennzeichnen, und Dinge, die der Öffentlichkeit zugänglich gemacht werden sollen, sollten in die Return-Anweisung aufgenommen werden. Außerdem sind diese Komponenten in sich geschlossene, isolierte Objekte, so dass sie globale Variablen nicht verschmutzen.

Ein Objekt, das den OOP-Prinzipien folgt, ist in sich geschlossen, folgt der Abstraktion, folgt der Kapselung und so weiter. Ohne Closures in Javascript ist dies schwer zu implementieren.

enter image description here

21voto

christian Nguyen Punkte 1342

Version Bild für diese Antwort: [Aufgelöst]

Vergessen Sie einfach alles und erinnern Sie sich: Wenn eine Variable irgendwo gebraucht wird, wird sie von Javascript nicht zerstört. Die Variable zeigt immer auf den neuesten Wert.

Beispiel 1:

enter image description here

Beispiel 2:

enter image description here

Beispiel 3: enter image description here

21voto

Nikhil Ranjan Punkte 974

Um Schließungen zu verstehen, müssen Sie sich in das Programm hineinversetzen und es buchstäblich so ausführen, als ob Sie die Laufzeit wären. Schauen wir uns dieses einfache Stück Code an:

Enter image description here

JavaScript führt den Code in zwei Phasen aus:

  • Kompilierungsphase // JavaScript ist keine rein interpretierte Sprache
  • Ausführungsphase

Wenn JavaScript die Kompilierungsphase durchläuft, werden die Deklarationen von Variablen und Funktionen herausgenommen. Dies wird "hoisting" genannt. Die in dieser Phase gefundenen Funktionen werden als Textblöcke im Speicher gespeichert, die auch als Lambda bezeichnet werden. Nach der Kompilierung tritt JavaScript in die Ausführungsphase ein, in der es alle Werte zuweist und die Funktion ausführt. Um die Funktion auszuführen, wird der Ausführungskontext vorbereitet, indem Speicher aus dem Heap zugewiesen und die Kompilierungs- und Ausführungsphase für die Funktion wiederholt wird. Dieser Speicherbereich wird Scope der Funktion genannt. Wenn die Ausführung beginnt, gibt es einen globalen Bereich. Scopes sind der Schlüssel zum Verständnis von Closures.

In diesem Beispiel wird im ersten Durchgang die Variable a definiert ist und dann f wird in der Kompilierungsphase definiert. Alle nicht deklarierten Variablen werden im globalen Bereich gespeichert. In der Ausführungsphase f wird mit einem Argument aufgerufen. f zugewiesen, und die Kompilierungs- und Ausführungsphase wird für ihn wiederholt.

Argumente werden auch in diesem lokalen Bereich gespeichert, um f . Wenn ein lokaler Ausführungskontext oder -bereich erstellt wird, enthält er einen Referenzzeiger auf seinen übergeordneten Bereich. Jeder Zugriff auf eine Variable folgt dieser lexikalischen Bereichskette, um ihren Wert zu finden. Wenn eine Variable nicht im lokalen Bereich gefunden wird, folgt sie der Kette und wird in ihrem übergeordneten Bereich gefunden. Dies ist auch der Grund, warum eine lokale Variable die Variablen im übergeordneten Bereich überschreibt. Der übergeordnete Bereich wird als "Closure" für einen lokalen Bereich oder eine Funktion bezeichnet.

Hier, wenn g wird ein lexikalischer Zeiger auf den elterlichen Geltungsbereich von f . Der Umfang der f ist der Abschluss für g . In JavaScript, wenn es einige Verweise auf Funktionen, Objekte oder Bereiche, wenn Sie sie irgendwie erreichen können, wird es nicht Garbage Collect bekommen. Wenn also myG läuft, hat es einen Zeiger auf den Bereich von f was sein Abschluss ist. Dieser Bereich des Speichers wird nicht Garbage Collect, auch nicht f zurückgekehrt ist. Für die Laufzeit ist dies ein Abschluss.

WAS ALSO IST EIN ABSCHLUSS?

  • Es handelt sich um eine implizite, permanente Verbindung zwischen einer Funktion und ihrer Bereichskette...
  • Die versteckte (Lambda-)Funktion einer Definition [[scope]] Hinweis.
  • Hält die Scope-Kette (verhindert Garbage Collection).
  • Sie wird bei jeder Ausführung der Funktion als "äußerer Umgebungsbezug" verwendet und kopiert.

IMPLIZITER ABSCHLUSS

var data = "My Data!";
setTimeout(function() {
  console.log(data); // Prints "My Data!"
}, 3000);

EXPLIZITE VERSCHLÜSSE

function makeAdder(n) {
  var inc = n;
  var sum = 0;
  return function add() {
    sum = sum + inc;
    return sum;
  };
}

var adder3 = makeAdder(3);

Ein sehr interessanter Vortrag über Verschlüsse und mehr ist Arindam Paul - JavaScript VM Interna, EventLoop, Async und ScopeChains .

21voto

enb081 Punkte 3551

Ein Verschluss ist eine Funktion innerhalb einer Funktion die Zugriff auf die Variablen und Parameter der "übergeordneten" Funktion hat.

Beispiel:

function showPostCard(Sender, Receiver) {

    var PostCardMessage = " Happy Spring!!! Love, ";

    function PreparePostCard() {
        return "Dear " + Receiver + PostCardMessage + Sender;
    }

    return PreparePostCard();
}
showPostCard("Granny", "Olivia");

21voto

Dmitry Frank Punkte 9899

Treffen Sie die illustrierte Erklärung : _Wie funktionieren JavaScript-Schließungen hinter den Kulissen?_ .

Der Artikel erklärt, wie die Scope-Objekte (oder LexicalEnvironment s) werden auf intuitive Weise zugewiesen und verwendet. Zum Beispiel für dieses einfache Skript:

"use strict";

var foo = 1;
var bar = 2;

function myFunc() {
  //-- Define local-to-function variables
  var a = 1;
  var b = 2;
  var foo = 3;
}

//-- And then, call it:
myFunc();

Bei der Ausführung des Top-Level-Codes haben wir die folgende Anordnung von Scope-Objekten:

Enter image description here

Und wenn myFunc() aufgerufen wird, haben wir die folgende Kette von Bereichen:

Enter image description here

Das Verständnis dafür, wie Scope-Objekte erstellt, verwendet und gelöscht werden, ist der Schlüssel zu einem Gesamtüberblick und zum Verständnis, wie Closures unter der Haube funktionieren.

Alle Einzelheiten finden Sie in dem oben genannten Artikel.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X