In JavaScript ist Gültigkeitsbereich der Kontext, in dem Code ausgeführt wird. Es gibt drei Arten von Bereichen: globaler Bereich, lokaler Bereich (manchmal als "Funktionsumfang" bezeichnet) und Eval-Bereich.
Code definiert mit var
Das Innere einer Funktion ist lokal begrenzt und nur für andere Ausdrücke in dieser Funktion "sichtbar", die Code in verschachtelten / untergeordneten Funktionen enthalten. Auf Variablen, die im globalen Gültigkeitsbereich definiert sind, kann von überall her zugegriffen werden, da es sich um die oberste Ebene und den letzten Stopp in der Gültigkeitsbereichskette handelt.
Untersuchen Sie den folgenden Code und stellen Sie sicher, dass Sie verstehen, dass jede Deklaration von foo
ist aufgrund des Umfangs einzigartig.
Beispiel: sample110.html
Stellen Sie sicher, dass Sie das jeweils verstehen foo
Variable enthält einen anderen Wert, da jeder in einem spezifisch abgegrenzten Bereich definiert ist.
Eine unbegrenzte Anzahl von Funktions- und Bewertungsbereichen kann erstellt werden, während eine JavaScript-Umgebung nur einen globalen Bereich verwendet.
Der globale Gültigkeitsbereich ist die letzte Station in der Gültigkeitsbereichskette.
Funktionen, die Funktionen enthalten, erstellen gestapelte Ausführungsbereiche. Diese miteinander verketteten Stapel werden oft als Scope-Chain bezeichnet.
Da logische Anweisungen (ob
) und Schleifenanweisungen (zum
) Erstellen Sie keinen Gültigkeitsbereich, die Variablen können sich überschreiben. Untersuchen Sie den folgenden Code, und stellen Sie sicher, dass Sie den Wert von kennen foo
wird neu definiert, während das Programm den Code ausführt.
Beispiel: sample111.html
So foo
ändert sich, während der Code ausgeführt wird, da JavaScript keine Blockfunktion, keinen globalen oder eval-Gültigkeitsbereich hat.
var
Innerhalb von Funktionen zum Deklarieren von Variablen und zum Vermeiden von Scope-GotchasJavaScript deklariert alle Variablen ohne a var
Deklaration (auch die in einer Funktion oder gekapselten Funktionen enthaltenen), die sich im globalen Bereich und nicht im beabsichtigten lokalen Bereich befindet. Schauen Sie sich den folgenden Code an und beachten Sie das ohne die Verwendung von var
Um den Balken zu deklarieren, ist die Variable tatsächlich im globalen Gültigkeitsbereich definiert und nicht im lokalen Gültigkeitsbereich.
Beispiel: sample112.html
Das Konzept zum Mitnehmen ist, dass Sie es immer verwenden sollten var
beim Definieren von Variablen innerhalb einer Funktion. Dies verhindert, dass Sie mit möglicherweise verwirrenden Umfangsproblemen fertig werden. Die Ausnahme zu dieser Konvention ist natürlich, wenn Sie im globalen Bereich Eigenschaften aus einer Funktion heraus erstellen oder ändern möchten.
Es gibt eine Suchkette, die folgt, wenn JavaScript nach dem mit einer Variablen verknüpften Wert sucht. Diese Kette basiert auf der Hierarchie des Bereichs. Im folgenden Code protokolliere ich den Wert von sayHiText
von dem func2
Funktionsumfang.
Beispiel: sample113.html
Wie ist der Wert von sayHiText
gefunden, wenn es nicht im Gültigkeitsbereich des enthalten ist func2
Funktion? JavaScript schaut zuerst in die func2
Funktion für eine Variable namens sayHiText
. Nicht finden func2
dort sieht es auf func2
s übergeordnete Funktion, func1
. Das sayHiText
Variable wird nicht im gefunden func1
Bereich auch, also fährt JavaScript mit dem globalen Bereich fort, wo sayHiText
gefunden wird, an welcher Stelle der Wert von sayHiText
geliefert wird. Ob sayHiText
war im globalen Geltungsbereich nicht definiert, nicht definiert
wäre von JavaScript zurückgegeben worden.
Dies ist ein sehr wichtiges Verständnis. Sehen wir uns ein weiteres Codebeispiel an, in dem wir drei Werte aus drei verschiedenen Bereichen herausgreifen.
Beispiel: sample114.html
Der Wert für z
ist lokal für die Bar
Funktion und den Kontext, in dem die console.log
wird aufgerufen. Der Wert für y
ist in dem foo
Funktion, die übergeordnet ist Bar()
, und der Wert für x
ist im globalen Bereich. Alle diese sind dem zugänglich Bar
Funktion über die Scope-Kette. Stellen Sie sicher, dass Sie verstehen, dass die referenzierenden Variablen im Bar
Die Funktion prüft die Variablen bis hinauf in der gesamten Scope-Kette.
Wenn Sie darüber nachdenken, unterscheidet sich die Scope-Kette nicht so sehr von der Prototyp-Kette. Beides ist einfach ein Weg, um einen Wert durch Überprüfen systematischer und hierarchischer Positionen zu ermitteln.
Im folgenden Codebeispiel wird eine Variable aufgerufen x
existiert in demselben Umfang, in dem es mit geprüft wird console.log
. Dieser "lokale" Wert von x
verwendet wird, und man könnte sagen, dass es den identisch benannten Schatten oder Masken gibt x
Variablen, die weiter oben in der Scope-Kette gefunden werden.
Beispiel: sample115.html
Denken Sie daran, dass die Suche nach dem Gültigkeitsbereich endet, wenn die Variable im nächstgelegenen verfügbaren Link der Kette gefunden wird, auch wenn derselbe Variablenname weiter oben in der Kette verwendet wird.
Da Funktionen den Gültigkeitsbereich bestimmen und Funktionen wie ein beliebiger JavaScript-Wert weitergegeben werden können, könnte man denken, dass das Entziffern der Gültigkeitsbereichskette kompliziert ist. Es ist eigentlich sehr einfach. Die Umfangskette wird basierend auf dem Ort einer Funktion während der Definition festgelegt, nicht während des Aufrufs. Dies wird auch als lexikalisches Scoping bezeichnet. Denken Sie lange und gründlich darüber nach, da die meisten Benutzer im JavaScript-Code häufig darüber stolpern.
Die Gültigkeitsbereichskette wird erstellt, bevor Sie eine Funktion aufrufen. Aus diesem Grund können wir Verschlüsse erstellen. Beispielsweise kann eine Funktion eine verschachtelte Funktion an den globalen Gültigkeitsbereich zurückgeben, jedoch kann unsere Funktion über die Gültigkeitsbereichskette weiterhin auf den Gültigkeitsbereich der übergeordneten Funktion zugreifen. Im folgenden Beispiel definieren wir a parentFunction
das gibt eine anonyme Funktion zurück, und wir rufen die zurückgegebene Funktion aus dem globalen Bereich auf. Weil unsere anonyme Funktion innerhalb von definiert wurde parentFunction
, Es hat immer noch Zugriff auf parentFunctions
Bereich, wenn es aufgerufen wird. Dies wird als Schließung bezeichnet.
Beispiel: sample116.html
Die Idee, die Sie hier mitnehmen sollten, ist, dass die Scope-Chain während der Definition wörtlich durch die Art und Weise bestimmt wird, wie der Code geschrieben wird. Durch das Weitergeben von Funktionen in Ihrem Code wird die Gültigkeitsbereichskette nicht geändert.
Nehmen Sie das, was Sie über die Umfangskette und die Suche nach Umfang in diesem Artikel gelernt haben, und eine Schließung sollte nicht übermäßig kompliziert sein. Im folgenden Beispiel erstellen wir eine Funktion namens countUpFromZero
. Diese Funktion gibt tatsächlich einen Verweis auf die darin enthaltene untergeordnete Funktion zurück. Wenn diese untergeordnete Funktion (verschachtelte Funktion) aufgerufen wird, hat sie aufgrund der Bereichskette weiterhin Zugriff auf den Bereich der übergeordneten Funktion.
Beispiel: sample117.html
Jedes Mal die countUpFromZero
Funktion aufgerufen wird, ist die anonyme Funktion im enthalten (und wird von diesem zurückgegeben) countUpFromZero
Funktion hat immer noch Zugriff auf den Umfang der übergeordneten Funktion. Diese Technik, die über die Scope-Chain ermöglicht wird, ist ein Beispiel für einen Verschluss.
Wenn Sie das Gefühl haben, ich habe zu vereinfachte Schließungen, sind Sie mit diesem Gedanken wahrscheinlich richtig. Ich tat dies jedoch absichtlich, da ich glaube, dass die wichtigen Teile aus einem soliden Verständnis der Funktionen und des Umfangs stammen, nicht notwendigerweise aus der Komplexität des Ausführungskontextes. Wenn Sie sich eingehend mit Verschlüssen befassen möchten, lesen Sie JavaScript Closures.