Wie JavaScript closures arbeiten?
Wie erklären Sie sich die JavaScript-closures jemand mit dem wissen der Konzepte, für die Sie bestehen (beispielsweise Funktionen, Variablen und dergleichen), aber nicht verstehen, Verschlüsse selbst?
Habe ich gesehen, das Schema Beispiel auf Wikipedia, aber leider hat es nicht geholfen.
Mein problem mit diesen und vielen Antworten ist, dass Sie den Ansatz einer abstrakten, theoretischen Perspektive, anstatt mit zu erklären, wieso einfach Verschlüsse sind notwendig, Javascript und den praktischen Situationen, in denen Sie Sie verwenden. Sie am Ende mit einem tl;dr-Artikel, die Sie haben, um slog durch, und die ganze Zeit denken, "aber, warum?". Ich würde einfach anfangen mit: - Verschlüsse sind eine nette Art des Umgangs mit den folgenden zwei Realitäten JavaScript: ein. Gültigkeitsbereich ist auf die Funktion Ebene, nicht auf der block-Ebene und b. vieles von dem, was Sie tun, in der Praxis in JavaScript ist asynchron - /event-driven.
Zum einen macht es die event-driven-code viel einfacher zu schreiben. Ich könnte Feuer eine Funktion, wenn die Seite geladen wird, um zu bestimmen, Einzelheiten über die HTML-oder die verfügbaren Funktionen. Ich kann definieren, und legen Sie einen handler in dieser Funktion und haben allen, die Kontext-info verfügbar, jedes mal, wenn der handler aufgerufen wird, ohne erneute Abfrage. Lösen Sie das problem einmal, Wiederverwendung auf jeder Seite, wo das hf ist es erforderlich, mit reduziertem Aufwand auf handler neu-Aufruf. Sie immer sehen, die gleichen Daten wieder zugeordnet zweimal in einer Sprache, die Sie nicht hat? Verschlüsse machen es viel einfacher, Sie zu vermeiden, dass Art der Sache.
Für Java-Programmierer, die kurze Antwort ist, dass es die Funktion entspricht einer inneren Klasse. Eine innere Klasse enthält auch eine implizite Zeiger auf eine Instanz der äußeren Klasse, und wird für viel den gleichen Zweck (das heißt, anlegen von event-Handlern).
Verstanden, dass diese viel besser von hier: javascriptissexy.com/understand-javascript-closures-with-ease. Noch benötigt ein closure auf Schließung nach dem Lesen der anderen Antworten. 🙂
Ich fand dieses Beispiel aus der Praxis sehr nützlich: youtube.com/watch?v=w1s9PgtEoJs
Zum einen macht es die event-driven-code viel einfacher zu schreiben. Ich könnte Feuer eine Funktion, wenn die Seite geladen wird, um zu bestimmen, Einzelheiten über die HTML-oder die verfügbaren Funktionen. Ich kann definieren, und legen Sie einen handler in dieser Funktion und haben allen, die Kontext-info verfügbar, jedes mal, wenn der handler aufgerufen wird, ohne erneute Abfrage. Lösen Sie das problem einmal, Wiederverwendung auf jeder Seite, wo das hf ist es erforderlich, mit reduziertem Aufwand auf handler neu-Aufruf. Sie immer sehen, die gleichen Daten wieder zugeordnet zweimal in einer Sprache, die Sie nicht hat? Verschlüsse machen es viel einfacher, Sie zu vermeiden, dass Art der Sache.
Für Java-Programmierer, die kurze Antwort ist, dass es die Funktion entspricht einer inneren Klasse. Eine innere Klasse enthält auch eine implizite Zeiger auf eine Instanz der äußeren Klasse, und wird für viel den gleichen Zweck (das heißt, anlegen von event-Handlern).
Verstanden, dass diese viel besser von hier: javascriptissexy.com/understand-javascript-closures-with-ease. Noch benötigt ein closure auf Schließung nach dem Lesen der anderen Antworten. 🙂
Ich fand dieses Beispiel aus der Praxis sehr nützlich: youtube.com/watch?v=w1s9PgtEoJs
InformationsquelleAutor |
Du musst angemeldet sein, um einen Kommentar abzugeben.
VORWORT: diese Antwort wurde geschrieben, wenn die Frage war:
Ich bin mir ziemlich sicher, ich war einer der wenigen Menschen, die versuchten, nehmen die erste Frage, buchstäblich. Da ist dann die Frage mutiert mehrmals, also meine Antwort mag jetzt scheinen unglaublich dumm & out-of-Platz. Hoffentlich wird die Allgemeine Vorstellung von der Geschichte bleibt der Spaß für einige.
Ich bin ein großer fan von Analogie und Metapher, wenn Sie erklären schwierige Konzepte, so lassen Sie mich versuchen, meine hand mit einer Geschichte.
Once upon a time:
Gab es eine Prinzessin...
Lebte Sie in einer wunderbaren Welt voller Abenteuer. Sie traf Ihre Prince Charming, fuhr herum Ihre Welt auf einem Einhorn, kämpften gegen Drachen, begegnet sprechenden Tieren, und viele andere phantastische Dinge.
Aber Sie würde immer wieder zurück zu Ihren langweiligen Welt der Arbeit und grown-ups.
Wäre und Sie sich oft erzählen Sie von Ihren neuesten erstaunlichen Abenteuer, wie eine Prinzessin.
Aber alle, die Sie sehen würden, ist ein kleines Mädchen...
...erzählen von Geschichten über Magie und fantasy.
Und obwohl die Erwachsenen wussten von echten Prinzessinnen, Sie würde nie glauben, in der Einhörner oder Drachen, weil Sie Sie nie sehen. Die Erwachsenen sagten, dass Sie existierten nur innerhalb des kleinen Mädchens Fantasie.
Aber wir kennen die wirkliche Wahrheit, dass das kleine Mädchen mit der Prinzessin in...
...ist wirklich eine Prinzessin mit einem kleinen Mädchen drin.
story()
- Funktion, die ist die einzige Schnittstelle dielittleGirl
Instanz macht in die Welt der Magie.So, hier
story
ist die Schließung aber hatte den code schonvar story = function() {}; return story;
dannlittleGirl
wäre die Schließung. Zumindest ist das der Eindruck, den ich von MDN ist die Verwendung des "private" - Methoden mit closures: "die drei öffentlichen Funktionen sind Verschlüsse, die die gleiche Umgebung."ja,
story
eine Schließung verweisen auf die Umwelt im Rahmen derprincess
.princess
ist auch noch ein anderesprincess
und dielittleGirl
teilen würde jeder Verweis auf eineparents
array existieren würde, wieder in die Umwelt/Bereich, wo dielittleGirl
vorhanden ist und dieprincess
definiert ist.Ich habe eine explizite code-Kommentar, um zu zeigen/andeuten, dass es mehr Operationen innerhalb des Körpers
princess
als das, was geschrieben ist. Leider ist diese Geschichte ist nun etwas deplatziert in diesem thread. Ursprünglich war die Frage zu Fragen, zu "erklären JavaScript-Verschlüssen ein 5yr alt"; meine Antwort war die einzige, die noch versucht, das zu tun. Ich bezweifle nicht, dass es würde haben kläglich versagt, aber zumindest diese Antwort könnte ' ve hatte die chance, zu halten, ein 5yr alt, von Interesse.Eigentlich ist mir das vollkommen Sinn. Und ich muss zugeben, endlich Verständnis JS-Verschluss durch mit Geschichten von Prinzessinnen und Abenteuer fühle ich mich irgendwie komisch.
InformationsquelleAutor
Dies ist ein Versuch zu klären, die mehrere (mögliche) Missverständnisse über Verschlüsse, die angezeigt werden in einigen der anderen Antworten.
James, ich sagte, die Schließung ist "wahrscheinlich" erstellt, die zum Zeitpunkt des Aufrufs der umschließenden Funktion, weil es plausibel ist, dass eine Implementierung könnte verzögern die Schaffung einer Schließung bis irgendwann später, wenn er entscheidet, eine Schließung ist absolut notwendig. Wenn es keine innere-Funktion definiert, die in der einschließenden Funktion, dann wird kein Verschluss benötigt wird. Also vielleicht könnte es warten, bis der erste innere Funktion erzeugt wird, dann erstellen Sie einen Verschluss aus der einschließende Funktion Anruf-Kontext.
Nehmen wir an, wir haben eine innere Funktion übergeben wird, eine andere Funktion, wo es verwendet wird, bevor die äußere Funktion liefert, und dann würden wir auch wieder die gleiche innere Funktion, die äußere Funktion. Es ist identisch die gleiche Funktion in beiden Fällen aber sind Sie sagen, dass vor der äußeren Funktion die innere Funktion ist "gebunden" an die call-stack, in der Erwägung, dass nach gibt es, die innere Funktion ist plötzlich gebunden zu einem Abschluss. Es verhält sich identisch in beiden Fällen; die Semantik identisch sind, so sind Sie nicht nur reden über Implementierungsdetails?
vielen Dank für dein feedback, und ich bin froh, dass ich Sie denken. Ich verstehe immer noch nicht, diese semantischen Unterschied zwischen der äußeren Funktion ist live-Kontext und dieser Kontext wird es, wenn man eine closure-Funktion zurück (wenn ich verstehe deine definition). Die innere Funktion ist das egal. Die Garbage collection kümmert sich nicht, da die innere Funktion verwaltet eine Referenz auf den context/Verschluss so oder so, und der Anrufer von der äußeren Funktion nur Tropfen seine Bezugnahme auf die Aufruf-Kontext. Aber es ist verwirrend für Menschen, und vielleicht besser, nur nennen es ein Anruf-Kontext.
Artikel ist schwer zu Lesen, aber ich denke, dass es wirklich unterstützt, was ich sage. Es sagt: "Ein Verschluss gebildet wird, durch Rücksendung ein function-Objekt [...] oder durch die direkte Zuweisung einer Referenz an eine solche Funktion Objekt, zum Beispiel eine Globale variable." Ich meine nicht, dass GC ist irrelevant. Eher, weil der GC, und da die innere Funktion wird an der äußeren Funktion Aufruf-Kontext (oder [[scope]], wie der Artikel sagt), dann ist es egal, ob die äußere Funktion rufen Sie zurück, weil die Bindung mit der inneren Funktion ist die wichtigste.
InformationsquelleAutor
Schrieb ich einen blog-post eine Weile zurück erklären Verschlüsse. Hier ist, was ich sagte über Verschlüsse in Bezug auf warum Sie wollen.
In diesem Sinne, lassen Sie eine Funktion, wirken ein bisschen wie ein Objekt mit privaten Attribute.
Full post:
Also, was sind diese Verschluss-thingys?
devError = emailError("[email protected]", errorString)
und dann meine eigenen version einer freigegebenen emailError Funktion?Nach Schneeschaufeln meinen Weg durch eine ganze Menge von 'splaining, begann ich endlich zu verstehen, was Sie waren. Ich dachte mir, "oh, wie seine privaten Variablen in einem Objekt?" und bam. Dies war die nächste Antwort, die ich Lesen.
Diese Erklärung und die damit verbundene perfekte Beispiel in den link (Schließung thingys) ist die beste Art zu verstehen, Verschlüsse und sollte direkt an der Spitze !
InformationsquelleAutor
Verschlüsse sind einfach:
Folgenden an einem einfachen Beispiel deckt alle wichtigen Punkte der JavaScript-Verschlüsse.*
Hier ist eine Fabrik, die produziert Taschenrechner kann addieren und multiplizieren:
Der entscheidende Punkt: Jedem Aufruf
make_calculator
erstellt eine neue lokale variablen
, der weiterhin verwendbar ist, die Rechneradd
undmultiply
Funktionen lange nachmake_calculator
gibt.Wenn Sie vertraut sind mit stack-frames, diese Rechner seltsam: Wie können Sie halten den Zugriff auf
n
nachmake_calculator
gibt? Die Antwort ist vorstellbar, dass JavaScript nicht verwenden "stack frames", sondern verwendet "heap-frames", die fortbestehen können, nachdem der Aufruf der Funktion, die Sie gemacht haben zurück.Innere Funktionen wie
add
undmultiply
, die Zugriff auf Variablen, die in einer äußeren Funktion**, aufgerufen werden Verschlüsse., Dass ist so ziemlich alles, was es zu Sperrungen.
* Zum Beispiel, umfasst es alle Punkte, die in die "Verschlüsse für Dummies" - Artikel gegeben, in eine andere Antwort, außer in Beispiel 6, das zeigt einfach nur, dass Variablen verwendet werden können, bevor Sie deklariert sind, eine schöne Tatsache zu wissen, aber nicht vollständig zu Schließungen. Es deckt auch alle Punkte in die akzeptierte Antwort, mit Ausnahme der Punkte (1), dass die Funktionen kopieren, Ihre Argumente in die lokalen Variablen (die benannte Funktion Argumente), und (2) dass das kopieren von zahlen schafft eine neue Nummer, aber das kopieren einer Objekt-Referenz bietet Ihnen eine weitere Referenz auf das gleiche Objekt. Diese sind auch gut zu wissen, aber wieder nicht vollständig zu Schließungen. Es ist auch sehr ähnlich wie das Beispiel in diese Antwort aber ein wenig kürzer und weniger Abstrakt. Es erstreckt sich nicht auf den Punkt diese Antwort oder dieser Kommentar, was das JavaScript macht es schwierig, den Stecker des aktuellen Wert der schleifenvariablen in Ihre innere Funktion: Das "plugging in" Schritt kann nur getan werden, mit einer Hilfsfunktion, umschließt Ihre innere Funktion und wird aufgerufen, auf jeder loop-iteration. (Streng genommen, ist die innere Funktion greift auf die helper-Funktion der Kopie der Variablen, anstatt alles angeschlossen ist.) Wieder sehr nützlich bei der Erstellung von Schließungen, aber nicht Teil von dem, was ein closure ist oder wie es funktioniert. Es gibt zusätzliche Verwirrung durch Verschlüsse arbeiten anders als in funktionalen Sprachen wie ML, wo Variablen sind gebunden an Werte eher als Stauraum, bietet einen Konstanten Strom von Menschen, die verstehen, Verschlüsse in einer Art und Weise (nämlich die "plugging in" Weg), das ist einfach falsch für JavaScript, wo Variablen sind immer gebunden an Speicherplatz, und nie zu Werten.
** der äußeren Funktion, wenn mehrere Ineinander verschachtelt sind, oder sogar im globalen Kontext, als diese Antwort Punkte deutlich heraus.
Da
first_calculator
ist ein Objekt (keine Funktion) sollten Sie nicht verwenden Klammern insecond_calculator = first_calculator;
, denn es ist ein Auftrag, nicht eine Funktion aufrufen. Um Ihre Frage zu beantworten, es würde dann nur ein Anruf make_calculator, also nur ein Rechner bekommen würde, und die Variablen first_calculator und second_calculator würde, beziehen sich beide auf dem selben Rechner, also die Antworten wäre 3, 403, 4433, 44330.InformationsquelleAutor
Wie würde ich es erklären, um ein sechs-Jahr-alten:
Wissen Sie, wie gewachsen-ups können ein Haus besitzen, und Sie nennen es nach Hause? Wenn eine Mutter ein Kind hat, das Kind nicht wirklich etwas besitzen, richtig? Aber seine Eltern ein Haus besitzen, so dass, wenn jemand fragt das Kind "Wo ist dein Zuhause?", er/Sie kann die Antwort "das Haus!", und zeigen Sie auf das Haus seiner Eltern. Eine "Schließung" ist die Fähigkeit des Kindes, immer (auch wenn im Ausland) in der Lage sein zu sagen, dass es ein Zuhause hat, auch wenn es tatsächlich die Eltern, die eigenen Haus.
InformationsquelleAutor
Können Sie erklären, Verschlüsse, um einen 5-jährigen?*
Ich denke immer noch, Googles Erklärung funktioniert sehr gut und ist prägnant:
*Eine C# - Frage
das ist nicht meine Kommentare, Sie sind ein Google-Entwickler
Zu sehen, dass innerFunction nicht verwiesen wird, die außerhalb outerFunction Bereich, ist der interpreter smart genug, um zu sehen, dass es braucht keinen Verschluss?
Der code ist "richtig", als ein Beispiel für eine closure, obwohl es nicht der Teil, der den Kommentar über mit der Schließung nach der outerFunction gibt. So ist es nicht ein tolles Beispiel. Es gibt viele andere Möglichkeiten, ein Verschluss verwendet werden könnten, die nicht mit der Rückkehr der innerFunction. z.B. innerFunction weitergegeben werden konnten, um eine andere Funktion zu, wo es heißt sofort oder gespeichert und rief einige Zeit später, und in allen Fällen, hat er Zugriff auf die outerFunction Kontext, der geschaffen wurde, als es aufgerufen wurde.
Nein, Moos ist falsch. Eine closure erstellt wird, unabhängig, ob die Funktion überhaupt entgeht dem Bereich, in dem es definiert ist, und eine vorbehaltlos erstellte Referenz auf das parent-die lexikalische Umgebung macht alle Variablen, die in den übergeordneten Rahmen für alle Funktionen, unabhängig davon, ob Sie geltend gemacht werden, die außerhalb oder innerhalb des Bereichs, in dem Sie erstellt wurden.
InformationsquelleAutor
Neige ich dazu, besser zu lernen, von GUT - /SCHLECHT-Vergleiche. Ich mag, um zu sehen, funktionierenden code, gefolgt von nicht funktionierenden code, jemand ist wahrscheinlich zu begegnen. Ich habe ein jsFiddle, die einen Vergleich und versucht einkochen die Unterschiede zu den einfachsten Erklärungen, die ich gefunden habe.
Verschlüsse richtig gemacht:
Im obigen code
createClosure(n)
aufgerufen wird, wird in jeder iteration der Schleife. Beachten Sie, dass ich den Namen der variablen
hervorheben, dass es ein neue variable erstellt, die in eine neue Funktion Rahmen und ist nicht die gleiche variable wieindex
die gebunden ist, um den äußeren Umfang.Dies schafft einen neuen Bereich, und
n
gebunden ist, der Umfang; das heißt, wir haben 10 separate Bereiche, eine für jede iteration.createClosure(n)
gibt eine Funktion zurückgibt, die die n in diesem Bereich.In jedem Bereich
n
gebunden ist, um welchen Wert es hatte, wenncreateClosure(n)
aufgerufen wurde, so wird die verschachtelte Funktion, wird zurückgegeben, wird immer wieder den Wert dern
hatte, dass Sie, wenncreateClosure(n)
aufgerufen wurde.Verschlüsse falsch gemacht:
Im obigen code die Schleife verschoben wurde innerhalb der
createClosureArray()
Funktion und die Funktion jetzt nur die Renditen der abgeschlossenen array, die auf den ersten Blick scheint mehr intuitiv.Was möglicherweise nicht offensichtlich ist, dass da
createClosureArray()
nur ein mal aufgerufen wird nur ein Bereich geschaffen für diese Funktion, anstatt eine für jede iteration der Schleife.In dieser Funktion eine variable namens
index
definiert ist. Läuft die Schleife und fügt Funktionen, die Arrays zurückgebenindex
. Beachten Sie, dassindex
definiert ist, innerhalb dercreateClosureArray
- Funktion, die nur jemals bekommt aufgerufen, eine Zeit.Weil es war nur ein Bereich innerhalb der
createClosureArray()
Funktionindex
nur gebunden auf einen Wert innerhalb dieses Bereichs. In anderen Worten, jedes mal, wenn die Schleife ändert sich der Wert derindex
, es ändert sich für alles, was, die darauf verweist, in diesem Bereich.Alle Funktionen Hinzugefügt, um das array wieder den GLEICHEN
index
variable aus der übergeordneten Bereich, wo es definiert wurde, anstatt 10 verschiedene, aus 10 verschiedenen Bereichen, wie das erste Beispiel. Das Endergebnis ist, dass alle 10 Funktionen geben den gleichen variable aus dem gleichen Bereich.Nachdem die Schleife beendet und die
index
getan wurde, geändert wird der end-Wert war 10, also jede Funktion Hinzugefügt, um das array liefert den Wert des einzigenindex
variable, die jetzt auf 10 gesetzt.Ergebnis
Mit
let
fürvar
behebt den Unterschied.Ist nicht hier "Schließung richtig gemacht" ist ein Beispiel für "Verschluss-Innenseite closure"?
Ich meine, jede Funktion ist technisch gesehen eine Schließung, aber der wichtige Teil ist, dass die Funktion definiert eine neue variable innerhalb. Die Funktion, die erhalten gibt nur Verweise
n
erstellt eine neue Schließung. Wir einfach nur wieder eine Funktion, so dass wir es speichern können, in dem array und rufen Sie es später.Wenn Sie wollen einfach nur speichern Sie das Ergebnis in das array in der ersten iteration dann könnte man inline es so:
arr[index] = (function (n) { return 'n = ' + n; })(index);
. Aber dann bist du speichern den resultierenden string in das array, anstatt eine Funktion aufzurufen, die Niederlagen der Punkt von meinem Beispiel.InformationsquelleAutor
Wikipedia auf Verschlüsse:
Technisch, in JavaScript, jede Funktion ist eine Schließung. Es hat immer ein Zugriff auf Variablen im umgebenden Bereich.
Seit -scope-Festlegung-Konstruktion in JavaScript ist eine Funktion, nicht um einen code-block, wie in vielen anderen Sprachen, , was wir in der Regel durch bedeutet Schließung in JavaScript ist ein - Funktion arbeiten mit globalen Variablen definiert, die bereits ausgeführt umliegenden Funktion.
Verschlüsse werden Häufig verwendet, zum erstellen von Funktionen mit einigen versteckten private Daten (aber es ist nicht immer der Fall ist).
ems
Obigen Beispiel ist die Verwendung einer anonymen Funktion, die einmal ausgeführt wurde. Aber es muss nicht sein. Es können benannt werden (z.B.
mkdb
) und später ausgeführt, Erzeugung einer Datenbank-Funktion jedes mal aufgerufen wird. Jede generierte Funktion wird über seine eigenen verborgenen Datenbank-Objekt. Ein weiteres Beispiel zur Verwendung von Schließungen ist, wenn wir nicht wieder eine Funktion, sondern ein Objekt mit mehreren Funktionen für verschiedene Zwecke, die jeweils die Funktion, die Zugang zu den gleichen Daten.InformationsquelleAutor
Ich zusammen eine interaktive JavaScript-tutorial zu erklären, wie Verschlüsse arbeiten.
Was ist eine Closure?
Hier ist eines der Beispiele:
InformationsquelleAutor
Geheimnisse für JavaScript-Funktionen sind die privaten Variablen
Jedes mal, wenn Sie nennen es, lokale variable "name" erstellt und der Vorname "Maria". Und jedes mal, wenn die Funktion beendet wird, ist die variable verloren und den Namen vergessen.
Als man sich vorstellen kann, weil die Variablen neu erstellt werden jedes mal, wenn die Funktion aufgerufen wird, und niemand wird wissen, es muss einen geheimen Ort, wo Sie gespeichert sind. Es könnte als Kammer des Schreckens oder stack oder lokalen Bereich aber es ist nicht wirklich wichtig. Wir wissen, Sie sind da, irgendwo versteckt in den Speicher.
Aber in JavaScript gibt es diese sehr spezielle Sache ist, dass die Funktionen, die erstellt wurden, in anderen Funktionen, kann das wissen auch die lokalen Variablen der Eltern und halten Sie Sie, solange Sie Leben.
So, solange wir in der parent-Funktion, es können eine oder mehrere untergeordnete Funktionen, die teilen das Geheimnis Variablen aus den geheimen Ort.
Aber die traurige Sache ist, wenn das Kind auch in einer privaten Variablen der übergeordneten Funktion, er würde auch sterben, wenn die Eltern endet, und die Geheimnisse, die würde mit Ihnen sterben.
So zu Leben, das Kind zu verlassen, bevor es zu spät ist
Und jetzt, obwohl Maria nicht mehr "läuft", die Erinnerung an Sie nicht verloren geht und Ihr Kind immer an Ihren Namen erinnern und andere Geheimnisse, die Sie teilten während Ihrer Zeit zusammen.
So, wenn Sie Sie nennen das Kind "Alice" wird Sie reagieren
Alles das ist dort ist zu sagen.
InformationsquelleAutor
Ich verstehe nicht, warum die Antworten sind so Komplex hier.
Hier ist eine Schließung:
Ja. Verwenden Sie vermutlich, dass viele Male ein Tag.
a
. Meiner Meinung nach, die überraschung ist, dass die JS-scope-Objekt ermöglichta
als Eigenschaft und nicht als eine Konstante. Und du wirst nur feststellen, dass wichtige Verhalten, wenn Sie es ändern, wie inreturn a++;
Genau das, was Jon sagte. Bevor ich endlich grokked Verschlüsse, die ich hatte eine harte Zeit der Suche nach praktischen Beispielen. Ja, floribon erstellt eine Schließung, aber für ungebildete mich würde dies brachte mir absolut nichts.
Dieses definiert nicht, was eine Schließung ist-es ist lediglich ein Beispiel. Und ist es nicht die nuance, was passiert, wenn der scope endet; ich glaube nicht, dass jemand hatte eine Frage über lexikalische scoping wenn alle Bereiche sind immer noch rund, und vor allem im Falle einer globalen variable.
InformationsquelleAutor
Beispiel für den ersten Punkt durch dlaliberte:
Kleine Klarstellung über eine mögliche Mehrdeutigkeit. Als ich sagte "In der Tat, die einschließende Funktion muss nicht mehr zurückkehren." Ich habe nicht bedeuten, "die keinen Wert zurückgeben", aber "noch aktiv". Damit das Beispiel nicht zeigen, dass die Aspekt, aber es zeigt einen anderen Weg der inneren Funktion übergeben werden kann, um den äußeren Umfang. Der wichtigste Punkt, den ich versuche zu machen, ist über die Zeit der Schöpfung der Schließung (für die einschließende Funktion), da einige Leute scheinen zu denken, es passiert, wenn die übergeordnete Funktion zurück. Ein anderes Beispiel ist erforderlich, um zu zeigen, dass der Verschluss wird erstellt, wenn eine Funktion genannt.
InformationsquelleAutor
Einer Schließung ist, wo eine innere Funktion hat Zugriff auf Variablen in der äußeren Funktion. Das ist wahrscheinlich die einfachste one-line-Erklärung können Sie sich für Sperrungen.
Eigentlich ist es nicht das alte Werte von der äußeren Funktion, die verfügbar sind, um die innere Funktion, aber die alte Variablen, die haben vielleicht neue Werte, wenn irgendeine Funktion in der Lage war, Sie zu ändern.
InformationsquelleAutor
Ich weiß, es gibt viele Lösungen bereits, aber ich denke, dass diese kleine und einfache Skript kann nützlich sein, um das Konzept veranschaulichen:
InformationsquelleAutor
Dann haben Sie einen Schlaf über und Sie einladen, Dan.
Sie sagen Dan bringen einem XBox-controller.
Dan lädt Paul.
Dan fragt Paul bringen einem controller. Wie viele Controller mitgebracht?
InformationsquelleAutor
JavaScript-Funktionen können auf Ihre:
Wenn eine Funktion greift auf seine Umgebung, dann ist die Funktion eine closure.
Beachten Sie, dass die äußeren Funktionen sind nicht erforderlich, obwohl Sie Vorteile bieten, die ich nicht hier diskutieren. Durch den Zugriff auf die Daten in seiner Umgebung, die eine Verschluss hält, die Daten lebendig. Im subcase von außen - /innen-Funktionen, eine äußere Funktion erstellen können lokale Daten und schließlich die Ausfahrt, und doch, wenn Sie keinen inneren Funktion(en) überleben, nachdem die äußere Funktion beendet, dann wird die innere Funktion(en) halten Sie die äußere Funktion lokalen Daten lebendig.
Beispiel für ein Verschluss verwendet die Globale Umwelt:
Vorstellen, dass der Stack-Overflow-Stimmen-und Stimmen-Unten-Taste-Ereignisse implementiert werden, wie Verschlüsse, voteUp_click und voteDown_click, dass der Zugriff auf externe Variablen isVotedUp und isVotedDown, die sind Global definiert. (Der Einfachheit halber beziehe ich mich auf StackOverflow die Frage, Vote-buttons, nicht die array-Antwort von Stimmberechtigt Tasten.)
Wenn der Benutzer auf die VoteUp-Taste, die voteUp_click Funktion überprüft, ob isVotedDown == true, um zu bestimmen, ob die Abstimmung nach oben oder nur stornieren, nach unten abstimmen. Funktion voteUp_click) ist ein closure, da Sie Zugriff auf seine Umgebung.
Alle diese vier Funktionen sind closures, wie Sie alle auf Ihre Umgebung.
InformationsquelleAutor
Autor Verschlüsse erklärt hat, Verschlüsse ziemlich gut, zu erklären, der Grund, warum wir Sie brauchen und auch erklärt, LexicalEnvironment die notwendig ist, um Verständnis Verschlüsse.
Hier ist die Zusammenfassung:
Was ist, wenn eine variable zugegriffen wird, ist es aber nicht local? Wie hier:
In diesem Fall wird der interpreter findet die variable in der
äußere
LexicalEnvironment
Objekt.Der Prozess besteht aus zwei Schritten:
Raum. Es ist eine aktuelle LexicalEnvironment Objekt. In dem Fall
oberhalb, Fenster (undefiniert ist an der Zeit, die von Funktion
Schöpfung).
Wenn eine Funktion erstellt wird, wird es eine versteckte Eigenschaft, die mit dem Namen [[Scope]], die auf den aktuellen LexicalEnvironment.
Wenn eine variable gelesen wird, aber können nicht überall gefunden werden, wird eine Fehlermeldung generiert.
Verschachtelte Funktionen
Funktionen können verschachtelt werden, eine innerhalb einer anderen, Sie bilden eine Kette von LexicalEnvironments, die auch als scope-chain.
Also, die Funktion g hat Zugang zu g, a und f.
Verschlüsse
Einer verschachtelten Funktion kann weiterleben, nachdem die äußere Funktion beendet wurde:
Kennzeichnung LexicalEnvironments:
Wie wir sehen, ist
this.say
ist eine Eigenschaft, die im user-Objekt, damit Sie weiterhin zu Leben, wenn der Benutzer abgeschlossen.Und wenn Sie sich erinnern, wenn
this.say
erstellt wird, ist es (wie jede Funktion) ruft eine interne Referenzthis.say.[[Scope]]
zu den aktuellen LexicalEnvironment. So, die LexicalEnvironment des aktuellen Benutzers Ausführung im Arbeitsspeicher verbleibt. Alle Variablen, die der Benutzer auch sind seine Eigenschaften, so dass Sie auch sorgfältig aufzubewahren, nicht junked als gewöhnlich.Der springende Punkt ist, um sicherzustellen, dass, wenn die innere Funktion zugreifen möchte, eine äußere variable, die in der Zukunft, es ist in der Lage, dies zu tun.
Zusammenfassen:
LexicalEnvironment.
jeder Zeit, auch wenn die äußere Funktion beendet ist.
Dies nennt man eine closure.
InformationsquelleAutor
Als Vater einer 6-jährigen, die derzeit unterrichten junger Kinder (und ein relativer Neuling zur Codierung mit keine formale Ausbildung, so dass Korrekturen erforderlich werden), ich denke, die Lektion würde-stick am besten durch "hands-on" spielen. Wenn der 6-jährige ist bereit zu verstehen, was ein Verschluss ist, dann sind Sie alt genug, um zu machen. Ich würde vorschlagen, kopieren Sie den code in jsfiddle.net erklären ein wenig, und verlassen Sie allein, um Braut einen einzigartigen song. Der erklärende text unten ist wahrscheinlich besser geeignet für einen 10-jährigen.
ANWEISUNGEN
DATEN: Daten ist eine Sammlung von Fakten. Es können zahlen, Wörter, Messungen, Beobachtungen oder auch nur Beschreibungen der Dinge. Können Sie nicht Anfassen, riechen oder schmecken. Sie können schreiben Sie es auf, es zu sprechen und zu hören. Sie könnten es verwenden, um erstellen berühren, riechen und schmecken mit einem computer. Es kann nutzbar gemacht werden, indem ein computer mithilfe von code.
CODE: Alle schreiben oben genannt code. Es ist in JavaScript geschrieben.
JAVASCRIPT: JavaScript ist eine Programmiersprache. Wie Englisch oder Französisch oder Chinesisch sind Sprachen. Es gibt viele Sprachen, die verstanden werden, die von Computern und anderen elektronischen Prozessoren. Für JavaScript zu verstehen, die von einem computer braucht es einen Dolmetscher. Stell dir vor, ein Lehrer, der nur Russisch spricht kommt um zu lehren Sie Ihre Klasse in der Schule. Wenn der Lehrer sagt "все садятся", die die Klasse nicht verstehen würde. Aber zum Glück hast du einen Russischen Schüler in Ihrer Klasse, sagt jeder, das bedeutet "alle hinsetzen" - so tun Sie alle. Die Klasse ist wie ein computer und die Russischen Schüler ist der interpreter. Für JavaScript die häufigsten interpreter aufgerufen wird, einen browser.
BROWSER: Wenn Sie eine Verbindung zum Internet auf einem computer, tablet oder Mobiltelefon, eine website zu besuchen, benutzen Sie eine browser. Beispiele, die Sie vielleicht wissen sind Internet Explorer, Chrome, Firefox und Safari. Kann der browser JavaScript versteht und dem computer sagen, was es tun muss. Die JavaScript-Anweisungen sind in Funktionen aufgerufen.
FUNKTION: EINE Funktion in JavaScript ist wie eine Fabrik. Es könnte eine kleine Fabrik mit nur einer Maschine im inneren. Oder es enthalten könnte viele weitere kleine Fabriken, jede mit vielen Maschinen zu tun verschiedenen Arbeitsplätze. In einer real-life-Kleider-Fabrik, die Sie haben könnten Unmengen von Stoff und Spulen von thread gehen und T-shirts und jeans kommen aus. Unsere JavaScript-Fabrik verarbeitet nur Daten, es kann nicht Nähen, ein Loch bohren oder Schmelzen des Metalls. In unserem JavaScript-Fabrik Daten geht und die Daten kommt.
Alle diese Daten-Zeug klingt ein bisschen langweilig, aber es ist wirklich sehr cool; vielleicht haben wir eine-Funktion, die sagt, ein Roboter, was Sie zum Abendessen machen. Sagen wir, ich lade Sie und Ihren Freund zu mir nach Hause. Sie möchten Hähnchenkeulen am besten, ich mag Würstchen, dein Freund will immer was Sie will und mein Freund kein Fleisch isst.
Ich habe keine Zeit, um Einkaufen zu gehen, so muss die Funktion wissen, was wir in den Kühlschrank, um Entscheidungen zu treffen. Jede Zutat hat eine andere Garzeit, und wir wollen, dass alles heiß serviert, die vom Roboter bei der gleichen Zeit. Wir brauchen, um die Funktion mit der Daten über das, was wir möchten, die Funktion könnte das "sprechen" Sie zum Kühlschrank, und die Funktion könnte die Steuerung des Roboters.
Eine Funktion der Regel hat einen Namen, Klammern und Klammern. Wie diese:
Beachten Sie, dass
/*...*/
und//
stop-code gelesen wird, durch den browser.NAME: aufrufen Sie können eine Funktion nur über was auch immer Wort, das Sie wollen. Das Beispiel "cookMeal" ist typisch für das verbinden von zwei Wörtern zusammen und geben der zweite Großbuchstabe am Anfang - aber das ist nicht notwendig. Es kann nicht ein Raum, in es, und es kann nicht sein, eine Nummer auf seinem eigenen.
KLAMMERN: "Klammern" oder
()
sind der Briefkasten, der an die JavaScript-Funktion werkseitig ist die Tür oder den Briefkasten in der Straße zum senden von Paketen von Informationen an das Werk. Manchmal ist die postbox kann markiert werden zum BeispielcookMeal(you, me, yourFriend, myFriend, fridge, dinnerTime)
, in dem Fall, dass Sie wissen, welche Daten Sie haben, um es zu geben.KLAMMERN: "Zahnspange", die wie folgt Aussehen
{}
sind die getönten Scheiben unserer Fabrik. Aus dem inneren der Fabrik, können Sie sehen, aber von außen kann man nicht sehen.DIE LANG-CODE-BEISPIEL OBEN
Unseren code beginnt mit dem Wort Funktion, so wissen wir, dass es eine ist! Dann den Namen der Funktion singen - das ist meine eigene Beschreibung, was die Funktion ist über. Dann Klammern (). Die Klammern sind auch immer es für eine Funktion. Manchmal sind Sie leer, und manchmal haben Sie etwas. Dieser hat das Wort:
(person)
. Nach diesem gibt es eine Klammer wie diese{
. Dies markiert den start der Funktion singen(). Es hat eine Partnerin, welche markiert das Ende der singen() wie diese}
Damit diese Funktion könnte etwas mit Gesang zu tun, und vielleicht müssen einige Daten über eine person. Es hat Anweisungen, die im inneren etwas zu machen, dass die Daten.
Nun, nach der Funktion singen(), in der Nähe des Ende der code ist die Zeile
VARIABLE: Die Buchstaben var stehen für "variable". Eine variable ist wie ein Umschlag. Auf der Außenseite dieser Umschlag mit der Aufschrift "Mensch". Auf der Innenseite enthält einen Zettel mit Informationen, die unsere Funktion braucht, einige Buchstaben und Leerzeichen zusammengefügt wie ein Stück Schnur (es heißt, einen string), mit einem Satz zu Lesen "eine alte Dame". Unsere Umschlag könnte andere Dinge wie zahlen genannt (ganze zahlen), Anweisungen (genannt Funktionen), Listen (genannt arrays). Da diese variable geschrieben wird, die außerhalb aller Klammern
{}
, und da kann man sehen durch die getönten Scheiben sind, wenn Sie innerhalb der Klammern, diese variable kann man von überall im code. Wir nennen dies eine 'Globale variable'.GLOBALE VARIABLE: person ist eine Globale variable, was bedeutet, dass, wenn Sie ändern Sie seinen Wert von "einer alten Dame" , "einen Jungen Mann", der person halten ein junger Mann bis Sie sich entscheiden wieder zu ändern und jede andere Funktion in den code sehen können, dass es ein junger Mann. Drücken Sie die F12 - Taste oder die Optionen betrachten, die Einstellungen zum öffnen der Entwickler-Konsole des Browsers und geben Sie "person" zu sehen, was diese Wert ist. Geben Sie
person="a young man"
es zu ändern, und geben Sie dann "person" wieder zu sehen, dass er sich verändert hat.Damit haben wir die Linie
Diese Zeile ruft die Funktion auf, als ob es riefe ein Hund
Wenn der browser geladen hat, den JavaScript-code ein und erreichte diese Linie, wird es starten Sie die Funktion. Ich füge die Zeile am Ende, um sicherzustellen, dass der browser alle Informationen, die es braucht, um es auszuführen.
Funktionen definieren Aktionen - die main-Funktion ist über den Gesang. Es enthält eine variable namens firstPart das gilt für den Gesang, über die person, das gilt für jeden einzelnen der Verse des Liedes: "Es war" + person + ", die verschluckt". Wenn Sie firstPart in die Konsole ein, werden Sie nicht eine Antwort bekommen, da die variable gesperrt ist, in eine Funktion - die kann der browser nicht sehen, im inneren die getönten Scheiben der Klammern.
VERSCHLÜSSE: Die Verschlüsse sind kleinere Funktionen, die innerhalb der großen singen() Funktion. Der kleine Fabriken innerhalb der großen Fabrik. Sie haben jeweils Ihre eigenen Klammern, was bedeutet, dass die Variablen, die innerhalb Sie kann nicht von außen gesehen werden. Das ist, warum die Namen der Variablen (Kreatur und Ergebnis) kann wiederholt werden, in der Verschlüsse, aber mit anderen Werten. Wenn Sie diese Variablen-Namen in der Konsole-Fenster, die Sie nicht erhalten Ihren Wert, weil Sie verborgen ist, indem Sie zwei Schichten von getönten Scheiben.
Sind die Verschlüsse alle wissen, was die singen() Funktion variable namens firstPart ist, da Sie sehen können, aus Ihren getönten Fenstern.
Nachdem die Verschlüsse stammen die Zeilen
Singen () - Funktion aufrufen jede dieser Funktionen in der Reihenfolge, wie Sie gegeben sind. Dann das singen () - Funktion ist die Arbeit getan.
InformationsquelleAutor
Okay, im Gespräch mit einem 6-jährigen Kind, würde ich vielleicht die Verwendung in folgenden Verbänden.
Vergleichen mit einer situation, wenn eine Tür verschlossen war, durch Entwurf und niemand im inneren (Allgemeine Ausführung der Funktion), und dann einige lokale Feuer entstehen und brennen unten die Zimmer (garbage-collector:D), und dann ein neues Zimmer gebaut und nun verlassen Sie möglicherweise eine andere Spielsachen gibt (neue function-Instanz), aber nie die gleichen Spielsachen, die wurden Links in den ersten Raum-Instanz.
Für eine erweiterte Kind wäre, würde ich etwas wie das folgende. Es ist nicht perfekt, aber es macht Sie Gefühl über das, was es ist:
Wie Sie sehen können, ist das Spielzeug Links in den Raum sind immer noch zugänglich über den Bruder und egal, ob der Raum gesperrt ist. Hier ist ein jsbin zu spielen, um mit.
InformationsquelleAutor
Eine Antwort für einen sechs-Jahr-alten (vorausgesetzt, er weiß, was eine Funktion ist und was eine variable ist, und welche Art von Daten):
Funktionen können Daten zurück. Eine Art von Daten können Sie die Rückgabe aus einer Funktion eine andere Funktion. Wenn diese neue Funktion wird zurückgegeben, alle Variablen und Argumente, mit denen in der Funktion, erstellt es geht nicht Weg. Anstatt, dass die parent-Funktion "geschlossen." In anderen Worten, nichts kann in Ihr Innerstes sehen und sehen Sie die Variablen, die es verwendet, außer für die Funktion, die es zurückgegeben. Dass die neue Funktion hat eine Besondere Fähigkeit, zurück zu blicken in der Funktion, die Sie erstellt und die Daten im inneren.
Einem anderen, sehr einfachen Weg, es zu erklären ist, in Bezug auf den Leistungsumfang:
Jedes mal, wenn Sie einen kleineren Bereich innerhalb eines größeren Bereichs, der kleinere Rahmen immer in der Lage, um zu sehen, was im größeren Umfang.
InformationsquelleAutor
Eine Funktion in JavaScript ist nicht nur ein Verweis auf eine Reihe von Anweisungen (wie in der C-Sprache), aber es enthält auch versteckte Daten-Struktur, welche aus Referenzen auf alle globalen Variablen, die Sie verwendet (erfassten Variablen). Solche zwei-Stück-Funktionen aufgerufen Verschlüsse. Jede Funktion in JavaScript kann als eine Schließung.
Verschlüsse sind Funktionen mit einem Zustand. Es ist etwas ähnlich wie "dieses" in dem Sinne, dass "dies" auch vom Staat für eine Funktion, aber Funktion und "dieses" sind separate Objekte ("dies" ist nur ein schicker parameter, und der einzige Weg, es zu binden, die dauerhaft auf eine Funktion zum erstellen einer Schließung). Während "dieser" und-Funktion immer getrennt Leben, eine Funktion kann nicht getrennt werden von der Schließung und die Sprache stellt keine Mittel für den Zugriff auf Variablen erfasst.
Weil alle diese externen Variablen verwiesen wird, die von einer lexikalisch verschachtelte Funktion sind eigentlich lokale Variablen in der Kette seiner lexikalisch umgebenden Funktionen (Globale Variablen kann angenommen werden, lokale Variablen von root-Funktion), und jede einzelne Ausführung einer Funktion erstellt neue Instanzen der lokalen Variablen, daraus folgt, dass jede Ausführung einer Funktion zurückgeben (oder sonst übertragen Sie es aus, wie das registrieren es als Rückruf) eine verschachtelte Funktion erstellt eine neue Schließung (mit eigenen potenziell einzigartigen verwiesen nichtlokale Variablen, die die Vertretung der Ausführungskontext).
Auch, es muss verstanden werden, dass lokale Variablen, die in JavaScript erstellt werden, nicht auf dem stack-frame, sondern auf dem heap, und nur vernichtet, wenn niemand auf Sie. Wenn eine Funktion gibt, Verweise auf die lokalen Variablen werden dekrementiert, aber Sie kann immer noch nicht null, wenn während der aktuellen Ausführung Sie wurde ein Teil von einem Verschluss und sind immer noch verwiesen wird, durch seine lexikalisch verschachtelte Funktionen (das kann nur geschehen, wenn die Verweise auf diese verschachtelte Funktionen zurückgegeben wurden oder anderweitig übertragen oder externer-code).
Beispiel:
InformationsquelleAutor
Würde ich einfach verweisen Sie Sie auf die Mozilla Verschlüsse Seite. Es ist die beste, die meisten knappe und einfache Erklärung der Schließung Grundlagen und praktische Anwendung, die ich gefunden habe. Es ist sehr empfehlenswert, wer JavaScript lernen.
Und ja, ich würde sogar empfehlen, es auf eine 6-jährige -- wenn der 6-jährige ist das lernen über die Verschlüsse, dann ist es logisch, Sie sind bereit zu verstehen, die knappe und einfache Erklärung im Artikel.
InformationsquelleAutor