Heim > Artikel > Web-Frontend > Vertiefte Kenntnisse des Umfangs und des variablen Hebens in JS
Scoping
Für Javascript-Anfänger ist der Umfang eines der verwirrendsten Dinge, denn das gilt nicht nur für Anfänger. Ich habe einige erfahrene JavaScript-Programmierer getroffen, aber sie verstehen den Umfang nicht genau. Der Grund, warum der JavaScript-Bereich verwirrend ist, liegt darin, dass seine Programmsyntax selbst der C-Sprachfamilie ähnelt. Mein Verständnis von Scope ist ein geschlossener Raum, der nur einen bestimmten Bereich betrifft und keinen Einfluss auf die Außenwelt hat. In einigen dieser Räume kann von außen nicht auf interne Variablen zugegriffen werden, auf externe Variablen kann jedoch von innen zugegriffen werden.
Variablen in der C-Sprache werden in globale Variablen und lokale Variablen unterteilt. Auf den Bereich globaler Variablen kann von jeder Datei und Funktion zugegriffen werden (für andere C-Dateien mit nicht variablen Definitionen müssen Sie natürlich die verwenden Zum Deklarieren des Schlüsselworts extern verwenden Sie das Schlüsselwort static (kann den Bereich auch auf die aktuelle Datei beschränken), und der Bereich lokaler Variablen ist der Bereich auf Blockebene von der Deklaration bis zur nächsten geschweiften Klammer. Java verfügt über keine globalen Variablen, sondern über Klassenvariablen, Mitgliedsvariablen und lokale Variablen. Der Geltungsbereich unterscheidet sich je nach öffentlichen, geschützten, privaten und anderen Zugriffsrechten.
Was sind die Bereiche von JS?
In ES5 gibt es für js nur zwei Formen des Bereichs: den globalen Bereich und den Funktionsbereich.
Der globale Bereich ist eigentlich der Bereich des globalen Objekts, auf das überall zugegriffen werden kann (sofern es nicht durch den Funktionsbereich abgedeckt ist).
Der Funktionsobjektumfang unterscheidet sich vom lokalen Variablenumfang von c. Sein Geltungsbereich ist der gesamte Funktionsumfang, unabhängig davon, ob er irgendwo in der Funktion deklariert wird! Dies wird als Heben bezeichnet, wobei es sich um das Konzept des variablen Hebens handelt. Aber keine Sorge, ich werde das Heben im Folgenden genauer erläutern.
In ES6 gibt es jedoch einen neuen Bereich auf Blockebene (den Bereich, der durch die nächsten geschweiften Klammern abgedeckt wird), der jedoch auf in der let-Methode deklarierte Variablen beschränkt ist.
Umfangsdemonstration:
Wenn Sie beim Definieren einer Variablen keine Variable schreiben, z. B. i = 0, wird sie als definiert Eine globale Variable ist der globale Bereich, andernfalls handelt es sich um eine lokale Variable und der Bereich ist der Funktionsbereich. Die Variable i=0 in der ersten Zeile oben wird als globale Variable bezeichnet, da sie im globalen Bereich deklariert wurde und nicht im Gültigkeitsbereich der Funktion liegt, also mit i=0 identisch ist.
Warum das Ergebnis so ist, erfahren Sie beim Weiterlesen.
Deklarationsformular
Variablendeklaration:
Funktionsdeklaration:
Variables Heben (Hoisting)
Hinterlässt eine Frage
Was wird der folgende Code ausgeben?
Ich habe viele Leute zu dieser Frage interviewt und die meisten von ihnen sagten, dass die Ausgabe das Datum ist. Aber das tatsächliche Ergebnis ist undefiniert. Warum ist das so? Hier kommt ein Konzept – Heben, was auf Chinesisch „variables Heben“ bedeutet. Die Erklärung zum Heben von Variablen in MDN lautet wie folgt:
var hoisting
Da Variablendeklarationen (und Deklarationen im Allgemeinen) verarbeitet werden, bevor Code ausgeführt wird, ist die Deklaration einer Variablen an einer beliebigen Stelle im Code erforderlich Dies entspricht der Deklaration an der Spitze. Dies bedeutet auch, dass eine Variable scheinbar verwendet werden kann, bevor sie deklariert wird. Dieses Verhalten wird als „Heben“ bezeichnet, da es so aussieht, als würde die Variablendeklaration an die Spitze der Funktion oder des globalen Codes verschoben.
Die Übersetzung dieser Passage lautet
Da die Variablendeklaration vor der Ausführung von Code verarbeitet wird, werden Variablen an einer beliebigen Stelle im Codebereich und am Anfang (oben) der lokalen Deklaration deklariert ist das gleiche. Das heißt, es sieht so aus, als ob eine Variable verwendet werden kann, bevor sie deklariert wird! Dieses Verhalten wird als „Heben“ bezeichnet, also als Heben von Variablen. Es sieht so aus, als würde die Deklaration der Variablen automatisch an den Anfang der Funktion oder des globalen Codes verschoben.
Hinweis: Nur die Deklaration wird aktualisiert, die Definition wird nicht aktualisiert.
Auf diese Weise hat der obige Code tatsächlich die folgende Form:
Sie sollten also verstehen, dass bei der Konsolenausgabe tmp Die Variable ist nur deklariert, aber nicht definiert, daher sollte die Ausgabe undefiniert sein.
Hier ist zu beachten, dass zwar alle Deklarationen (einschließlich var, function von ES5 und function *, let, const, class von ES6) hochgestuft werden, var, function, function * und let, const, class jedoch eine Verbesserung darstellen ist nicht dasselbe! Die spezifischen Gründe finden Sie hier (die allgemeine Bedeutung ist, dass let, const und class zwar ebenfalls heraufgestuft werden, aber nicht initialisiert werden. Wenn Sie zu diesem Zeitpunkt darauf zugreifen, wird eine ReferenceError-Ausnahme gemeldet. Sie müssen warten bis Die Anweisung wird initialisiert und der Zustand vor der Initialisierung wird als zeitliche Totzone bezeichnet. Schauen wir uns einen Code an, um herauszufinden:
Hier wird a heraufgestuft, aber weil es später definiert wird, wird undefiniert ausgegeben
Obwohl a ist hier beworben, aber es wurde ein Zitierfehler gemeldet!
Der Grund dafür ist folgender
Aus diesem Grund besteht der empfohlene Ansatz darin, beim Deklarieren der Variablendomäne alle Variablen in den Bereich (globaler Bereich oder Funktionsbereich) zu schreiben dass der Code klarer aussieht und es einfacher ist zu erkennen, welche Variable aus dem Funktionsbereich und welche aus der Bereichskette stammt (dieser Artikel wird nicht mehr darüber erklären, bitte lesen Sie ihn selbst. Ich werde füge bei Gelegenheit weitere Details hinzu).
Wiederholen Sie die Aussage
Die obige Ausgabe lautet tatsächlich: 1 2 2. Obwohl es den Anschein hat, dass x, wie oben erwähnt, zweimal deklariert wird, gibt es in js nur zwei Arten von Variablenvariablen: den globalen Bereich und den Funktionsbereich, und die Deklaration wird heraufgestuft, sodass x tatsächlich nur einmal an der Spitze deklariert wird , wird die Deklaration von var x=2 ignoriert und nur für die Zuweisung verwendet. Mit anderen Worten, der obige Code stimmt tatsächlich mit dem folgenden überein.
Das Problem der gleichzeitigen Förderung von Funktionen und Variablen
Was passiert, wenn Funktions- und Variablentypen gleichzeitig deklariert werden? Schauen Sie sich den Code unten an
Die obige Ausgabe ist eigentlich: function foo(){}, was der Funktionsinhalt ist.
Und was ist, wenn es in dieser Form vorliegt?
Die Ausgabe wird: undefiniert
Warum ist das so?
Es stellt sich heraus, dass die Funktionsförderung in zwei Situationen unterteilt ist:
Erstens: Funktionsdeklaration. Es ist A oben, Funktion foo(){} in der Form
Andere: Funktionsausdruck. Es ist B oben, var foo=function(){} in der Form
Die zweite Form ist eigentlich die Deklarationsdefinition der var-Variablen, daher sollte es verständlich sein, dass das Ausgabeergebnis von B oben ist ist undefiniert.
Die erste Form der Funktionsdeklaration wird während der Promotion komplett aktualisiert, einschließlich des Funktionsdefinitionsteils! Daher entspricht A der folgenden Methode!
Der Grund ist, dass: 1. Die Funktionsdeklaration nach oben befördert wird; 2. Die Deklaration erfolgt nur einmal, also die nachfolgende Deklaration von var foo='i „Am Text“ wird ignoriert.
Und Funktionsdeklarationen haben Vorrang vor Variablendeklarationen, daher ist die Ausgabe in der folgenden Form auch der Funktionsinhalt:
Zusammenfassung
Um den Umfang und das Heben von JS vollständig zu verstehen, denken Sie einfach an die folgenden drei Punkte:
1. Alle Deklarationen werden an die Spitze des Geltungsbereichs befördert
2. Dieselbe Variable Die Deklaration wird nur einmal vorgenommen und daher werden andere Deklarationen ignoriert
3. Funktionsdeklarationen haben Vorrang vor Variablendeklarationen und Funktionsdeklarationen werden zusammen mit Definitionen hochgestuft
Hinweis:
Mit der with-Anweisung können Sie die Bereichskette des Laufzeitkontexts vorübergehend ändern. Wenn Sie zu diesem Zeitpunkt auf eine nicht var-definierte Variable zugreifen, wird zuerst auf die Attribute des Objekts in with zugegriffen, und dann wird es gelöscht Überprüfen Sie diese Eigenschaft in der Kette.