Erfordert eine (JS) Closure eine Funktion innerhalb einer Funktion

8

Ich habe ein wenig Schwierigkeiten mit dem inhärenten Konzept einer Schließung. Ich bekomme die Grundidee, aber hier ist das Ding: Ich dachte, dass technisch "es eine Schließung" in jeder Javascript-Funktion gibt. Um Wikipedia zu zitieren:

  

In der Informatik ein Verschluss (auch lexikalischer Verschluss, Funktionsverschluss   oder Funktionswert) ist eine Funktion zusammen mit einer Referenzierung   Umgebung für die nichtlokalen Namen (freie Variablen) dieser Funktion.   Eine solche Funktion wird als "geschlossen" über ihre freien Variablen bezeichnet.

Da Sie also Variablen innerhalb einer Funktion definieren können, sind sie für den Rest Ihres Codes "geschlossen", und das sehe ich als eine Schließung. Also, wie ich es verstehe:

%Vor%

Ist ein (nicht sehr nützliches) Beispiel für eine Schließung. Oder verdammt, auch nur das:

%Vor%

Aber ich denke, mein Verständnis könnte falsch sein. Andere sagen mir, dass etwas, um eine Schließung zu sein, ein Zustand bleiben muss, und da nichts über diesen Code hinaus besteht, ist es nicht wirklich eine Schließung. Das bedeutet, dass Sie Folgendes benötigen:

%Vor%

oder sogar (um Un-Änderbarkeit zu gewährleisten):

%Vor%

Also, technisch gesprochen (ich weiß, dass einige der Beispiele praktisch sinnlos sind, aber) welche der obigen Beispiele sind eigentlich Beispiele für Schließungen. Und muss ein Abschluss nur ein Leerzeichen sein (dh innerhalb einer JS-Funktion), wo Variablen gespeichert werden können, auf die nicht von außen zugegriffen werden kann, oder ist Persistenz ein Schlüsselelement der Definition eines Abschlusses?

BEARBEITEN

Habe gerade die Wiki-Definition für das "closures" -Tag auf Stack Overflow bemerkt:

  

Eine Schließung ist eine erstklassige Funktion, die sich auf (schließt über) bezieht   Variablen aus dem Bereich, in dem sie definiert wurde. Wenn der Verschluss still ist   existiert, nachdem sein definierender Bereich endet, die Variablen, die er schließt   wird auch weiterhin existieren.

Obwohl das SO-Wiki sicherlich keine endgültige Autorität ist, scheint der erste Satz mit meinem Verständnis des Begriffs zu korrelieren. Der zweite Satz schlägt dann vor, wie eine Schließung verwendet werden kann, aber es scheint nicht wie eine Anforderung.

BEARBEITEN # 2

Falls es aus den verschiedenen Antworten hier, der Wikipedia-Antwort und der Antwort des Tags nicht klar ist, scheint es keinen klaren Konsens darüber zu geben, was das Wort "Schließung" überhaupt bedeutet. Während ich alle Antworten bis jetzt schätze und sie alle einen Sinn ergeben, wenn Sie mit der Definition des Autors von Schließung gehen, ist das, wonach ich wirklich suche, ... ... gibt es eine wirklich "autoritative" Definition des Wortes ( und wenn ja, wie gilt das für alles oben genannte?

    
machineghost 17.08.2011, 17:20
quelle

3 Antworten

9

Sie werden durch eine falsche Annahme irregeführt, woher das Wort "Schließung" kommt.

In einem sprachtheoretischen Kontext besteht der Zweck einer Schließung darin, dass die Funktion sich auf Variablen beziehen kann, die außerhalb ihrer eigenen Definition deklariert sind. Es ist unerheblich, ob es interne Variablen gibt oder ob die internen Variablen von außen nicht sichtbar sind. Mit anderen Worten, es geht darum, out von der Funktion zu seiner Definitionsumgebung zu sehen und nicht in von außerhalb der Funktion zu sehen.

Warum also das komische Wort? Sehen Sie sich die Funktion in Ihrem letzten Beispiel an:

%Vor%

Diese Funktion enthält eine Erwähnung der Variable a , die nicht im Funktionskörper selbst definiert ist. Es ist eine "freie" Variable des Funktionskörpers, eine Art "Loch" in der Definition. Wir können die Funktion nicht ausführen, ohne auf irgendeine Weise zu wissen, auf welche Variable sich der Bezeichner a im Körper bezieht. Durch die Bildung eines Abschlusses zur Laufzeit wird dieser "offene" Funktionskörper mit einem Verweis auf die entsprechende Variable verknüpft, wodurch das Loch in der Definition geschlossen wird. Und hier kommt der Name her.

(Wenn Sie die vollständig technische Erklärung wollen, ist das zugrundeliegende Konzept das eines "geschlossenen" Begriffs in der Lambda-Kalkül, was bedeutet, dass keine freie Variablen hat. Nur geschlossene Begriff haben unabhängige Bedeutungen. Eine Schließung ist dann die Kombination eines (normalerweise kompilierten) nicht-geschlossenen Teils des Quellcodes, zusammen mit den kontextuellen Informationen, die es sich wie ein geschlossener Begriff verhalten lassen und daher ausführbar sind.

Addendum : Im allgemeinen Idiom

%Vor%

Der Punkt ist nicht , um eine Schließung zu erhalten (Sie erhalten natürlich eine, aber es macht für Sie nichts interessantes), aber einen lokalen Bereich für die Variable blah . Ein lokaler Bereich ist konzeptuell eine ganz andere Sache als eine Schließung - tatsächlich erstellen die meisten C-Lookalikes außer Javascript sie in jedem {} -Block, während sie möglicherweise überhaupt keine Closures haben.

    
Henning Makholm 17.08.2011, 17:36
quelle
2

Keine Ihrer Proben sind technisch gesehen Verschlüsse. (Aber die vierte Probe kann unter bestimmten Umständen als solche klassifiziert werden, siehe unten)

Closure ist eine Datenstruktur, die den Verweis auf eine Funktion und eine nicht leere Liste von Callframes (oder Bereichen) kombiniert, die zum Zeitpunkt der Deklaration aktiv sind.

Closure wird erstellt, indem Code ausgeführt wird, der die Deklaration einer Funktion enthält, die Variablen aus äußeren Bereichen verwendet. In diesem Fall muss die Laufzeit beim Ausführen des Codes nicht nur eine Referenz auf die Funktion, sondern die Closure-Struktur - Funktionsreferenz und Referenz auf ihre aktuelle Umgebung - eine Liste von Call-Frames erzeugen, die verwendete äußere Variablen enthalten.

Zum Beispiel in meinen TIScript Call-Frames werden auf Stapel ersetzt - wenn Sie von einer Funktion beenden, wird seine Der Aufrufrahmen, der die Sammlung der Variablen enthält, die er verwendet, wird vom Stapel gelöscht. Die Schließerstellung geschieht in meinem Fall, wenn: VM die Anweisung zur Funktionsdeklaration erfüllt und diese Funktion (durch den Compiler) als diejenige gekennzeichnet ist, die äußere Variablen verwendet. In diesem Fall wird die aktuelle Kette von Aufrufrahmen, die benutzte Variablen enthalten, vom Stapel zum Heap verschoben - in GCable-Datenobjekte konvertiert und auf die Funktion und verwiesen, deren Aufrufkette als Referenz gespeichert wird.

Ihr vierter Fall erfordert physisch keine Schließung - es müssen keine Call-Frames für die spätere Verwendung gespeichert werden - bar.baz enthält nur eine Zahl - keine Referenz auf die Funktion.

Aber das:

%Vor%

erstellt den Abschluss in bar.baz field. Wenn Sie später% co_de aufrufen, wird der Funktionscode ausgeführt und der Wert von 'a' wird aus dem Verweis auf den äußeren Aufrufrahmen übernommen, der in closure gespeichert ist.

Hoffe, es macht etwas für dich.

    
c-smile 17.08.2011 19:05
quelle
0

Closures in JavaScript (und anderen Sprachen) werden verwendet, um den Umfang zu steuern und zu definieren. Es ist nicht erforderlich, dass Sie eine Funktion innerhalb einer Funktion definieren, damit sie sich als Abschluss qualifiziert. Der Körper einer Funktion ist ein Closure. Eine häufigere Verwendung besteht darin, eine lokale Bereichsvariable zu deklarieren, die zu einem privaten oder ausgeblendeten Element eines anderen Objekts oder einer anderen Funktion wird, die Sie zurückgeben. Dies ist jedoch keine feste Regel.

    
g.d.d.c 17.08.2011 17:28
quelle

Tags und Links