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.

7voto

poushy Punkte 1024

Meine Sicht der Schließungen:

Verschlüsse lassen sich mit einem Buch mit Lesezeichen in einem Bücherregal vergleichen.

Nehmen wir an, Sie haben ein Buch gelesen und Ihnen gefällt eine Seite des Buches. Sie setzen ein Lesezeichen auf diese Seite, um sie zu verfolgen.

Wenn Sie das Buch zu Ende gelesen haben, brauchen Sie das Buch nicht mehr, aber Sie wollen Zugang zu dieser Seite haben. Du hättest die Seite einfach ausschneiden können, aber dann hättest du den Zusammenhang mit der Geschichte verloren. Also legen Sie das Buch mit dem Lesezeichen zurück in Ihr Bücherregal.

Dies ist ähnlich wie ein Verschluss. Das Buch ist die äußere Funktion, und die Seite ist Ihre innere Funktion, die von der äußeren Funktion zurückgegeben wird. Das Lesezeichen ist der Verweis auf Ihre Seite, und der Kontext der Geschichte ist der lexikalische Bereich, den Sie beibehalten müssen. Das Bücherregal ist der Funktionsstapel, der erst dann von den alten Büchern bereinigt werden kann, wenn Sie an der Seite festhalten.

Code-Beispiel:

function book() {
   var pages = [....]; //array of pages in your book
   var bookMarkedPage = 20; //bookmarked page number
   function getPage(){
       return pages[bookMarkedPage];
   }
   return getPage;
}

var myBook = book(),
    myPage = myBook.getPage();

Wenn Sie die book() Funktion wird im Stack Speicher für die Funktion reserviert, die darin ausgeführt werden soll. Da die Funktion jedoch eine Funktion zurückgibt, kann der Speicher nicht freigegeben werden, da die innere Funktion Zugriff auf die Variablen aus dem Kontext außerhalb der Funktion hat, in diesem Fall "pages" und "bookMarkedPage".

So rufen Sie effektiv book() gibt einen Verweis auf einen Abschluss zurück, d.h. nicht nur eine Funktion, sondern auch einen Verweis auf das Buch und seinen Kontext, d.h. einen Verweis auf die Funktion getPage Zustand der Seiten y bookMarkedPage Variablen.

Einige Punkte sind zu beachten:

Punkt 1: Das Bücherregal hat, genau wie der Funktionsstapel, nur begrenzten Platz, also nutzen Sie ihn sinnvoll.

Punkt 2: Überlegen Sie, ob Sie das ganze Buch festhalten müssen, wenn Sie nur eine einzige Seite verfolgen wollen. Sie können einen Teil des Speichers freigeben, indem Sie nicht alle Seiten des Buches speichern, wenn der Verschluss zurückgegeben wird.

Dies ist meine Sichtweise von Closures. Ich hoffe, es hilft, und wenn jemand denkt, dass dies nicht korrekt ist, lassen Sie es mich bitte wissen, da ich sehr daran interessiert bin, noch mehr über Scopes und Closures zu verstehen!

0 Stimmen

Eine sehr kluge Analogie!

6voto

David Rosson Punkte 934

Am besten ist es, diese Konzepte schrittweise zu erklären:

Variablen

console.log(x);
// undefined

Hier, undefined ist die Art von JavaScript zu sagen: "Ich habe keine Ahnung, was x bedeutet".

Variablen sind wie Tags.

Sie können sagen, Tag x weist auf den Wert hin 42 :

var x = 42;
console.log(x);
// 42

Jetzt weiß JavaScript, was x bedeutet.

Sie können eine Variable auch neu zuordnen.

Tag erstellen x auf einen anderen Wert verweisen:

x = 43;
console.log(x);
// 43

Jetzt x bedeutet etwas anderes.

Umfang

Wenn Sie eine Funktion erstellen, verfügt die Funktion über eine eigene "Box" für Variablen.

function A() {
  var x = 42;
}

console.log(x);

// undefined

Von außen kann man nicht sehen, was sich in der Schachtel befindet.

Aber vom Inneren der Box aus kann man sehen, was außerhalb der Box ist:

var x = 42;

function A() {
  console.log(x);
}

// 42

Innere Funktion A haben Sie "scope access" zu x .

Wenn Sie nun zwei Boxen nebeneinander haben:

function A() {
  var x = 42;
}

function B() {
  console.log(x);
}

// undefined

Innere Funktion B haben Sie keinen Zugriff auf Variablen innerhalb der Funktion A .

Wenn Sie jedoch die Funktion define B innere Funktion A :

function A() {

  var x = 42;

  function B() {
    console.log(x);
  }

}

// 42

Sie haben jetzt "Zugriffsmöglichkeiten".

Funktionen

In JavaScript führen Sie eine Funktion aus, indem Sie sie aufrufen:

function A() {
  console.log(42);
}

Zum Beispiel so:

A();

// 42

Funktionen als Werte

In JavaScript können Sie einen Tag auf eine Funktion verweisen, genau wie auf eine Zahl:

var a = function() {
  console.log(42);
};

Variabel a jetzt eine Funktion bedeutet, können Sie sie ausführen.

a();
// 42

Sie können diese Variable auch weitergeben:

setTimeout(a, 1000);

In einer Sekunde (1000 Millisekunden) wird die Funktion a verweist, wird aufgerufen:

// 42

Umfang des Abschlusses

Wenn Sie nun Funktionen definieren, haben diese Funktionen Zugriff auf ihre äußeren Bereiche.

Wenn Sie Funktionen als Werte weitergeben, wäre es ärgerlich, wenn dieser Zugriff verloren geht.

In JavaScript behalten Funktionen ihren Zugriff auf Variablen des äußeren Bereichs. Selbst wenn sie weitergereicht werden, um an anderer Stelle ausgeführt zu werden.

var a = function() {

  var text = 'Hello!'

  var b = function() {
    console.log(text);
    // inside function `b`, you have access to `text`
  };

  // but you want to run `b` later, rather than right away
  setTimeout(b, 1000);

}

Was geschieht nun?

// 'Hello!'

Oder bedenken Sie dies:

var c;

var a = function() {

  var text = 'Hello!'

  var b = function() {
    console.log(text);
    // inside function `b`, you have access to `text`
  };

  c = b;

}

// now we are out side of function `a`
// call `a` so the code inside `a` runs
a(); 

// now `c` has a value that is a function
// because what happened when `a` ran

// when you run `c`
c();

// 'Hello!'

Sie können weiterhin auf Variablen im Schließungsbereich zugreifen.

Auch wenn a ist beendet und Sie führen jetzt c außerhalb von a .

Was hier gerade passiert ist, wird als Verschluss ' in JavaScript.

6voto

Taye Punkte 797

Ein Abschluss besteht im Wesentlichen aus zwei Dingen: - eine Funktion - einen privaten Bereich, auf den nur diese Funktion zugreifen kann

Es ist, als würde man eine Funktion mit einem Mantel umhüllen.

Einem 6-Jährigen könnte man es also mit einer Analogie erklären. Nehmen wir an, ich baue einen Roboter. Dieser Roboter kann viele Dinge tun. Unter anderem habe ich ihn so programmiert, dass er die Anzahl der Vögel zählt, die er am Himmel sieht. Jedes Mal, wenn er 25 Vögel gesehen hat, soll er mir sagen, wie viele Vögel er von Anfang an gesehen hat.

Ich weiß nicht, wie viele Vögel er gesehen hat, außer er hat es mir gesagt. Nur er weiß es. Das ist der private Bereich. Das ist im Grunde der Speicher des Roboters. Sagen wir, ich habe ihm 4 GB gegeben.

Wenn er mir sagt, wie viele Vögel er gesehen hat, ist das die Rückgabefunktion. Auch das habe ich erstellt.

Diese Analogie ist ein bisschen ätzend, aber ich denke, jemand könnte sie verbessern.

6voto

cube Punkte 1724

Das Wort Verschluss bezieht sich einfach auf die Möglichkeit des Zugangs zu Objekte (Sechsjährige: Dinge), die sind geschlossen (sechsjährig: privat) innerhalb einer Funktion (Sechsjähriger: Kasten). Auch wenn die Funktion (sechsjährig: Box) ist aus der Umfang (Sechsjähriger: weit weggeschickt).

6voto

Javier La Banca Punkte 329

Der einfachste Anwendungsfall, der mir einfällt, ist JavaScript-Schließungen ist das Modul-Muster. Beim Modulmuster definieren Sie eine Funktion und rufen sie unmittelbar danach in einem so genannten Immediately Invoked Function Expression (IIFE) auf. Alles, was Sie innerhalb dieser Funktion schreiben, hat privaten Geltungsbereich, da es innerhalb der Schließung definiert ist so dass Sie die Privatsphäre in JavaScript "simulieren" können. Zum Beispiel so:

 var Closure = (function () {
    // This is a closure
    // Any methods, variables and properties you define here are "private"
    // and can't be accessed from outside the function.

    //This is a private variable
    var foo = "";

    //This is a private method
    var method = function(){

    }
})();

Wenn Sie hingegen eine oder mehrere Variablen oder Methoden außerhalb der Closure sichtbar machen möchten, können Sie sie in einem Objektliteral zurückgeben. Zum Beispiel so:

var Closure = (function () {
  // This is a closure
  // Any methods, variables and properties you define here are "private"
  // and can't be accessed from outside the function.

  //This is a private variable
  var foo = "";

  //This is a private method
  var method = function(){

  }

  //The method will be accessible from outside the closure
  return {
    method: method
  }

})();

Closure.method();

Ich hoffe, es hilft. Mit freundlichen Grüßen,

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