Vor kurzem lese ich "JavaScript Advanced Programming 3" erneut und habe das Gefühl, dass ich einige Blogs schreiben sollte, um einige der von mir gelernten Wissen aufzuzeichnen, sonst werde ich es vergessen. Was ich heute zusammenfassen möchte, ist die JS -Ausführungsumgebung und den JS -Umfang.
Lassen Sie uns zunächst über die Ausführungsumgebung sprechen
1. Ausführungsumgebung
Das Konzept im Buch, die Ausführungsumgebung, definiert andere Daten, die Variablen oder Funktionen Zugriff haben und ihre jeweiligen Verhaltensweisen bestimmt. Jede Ausführungsumgebung ist mit einem variablen Objekt zugeordnet. Alle in der Umgebung definierten Variablen und Funktionen werden in diesem Objekt gespeichert. Obwohl wir beim Schreiben von Code nicht auf dieses Objekt zugreifen können, verwendet der Parser ihn beim Verarbeiten von Daten im Hintergrund.
Die Ausführungsumgebung ist ein Konzept, ein Mechanismus, der definiert, ob eine Variable oder Funktion die Erlaubnis hat, auf andere Daten zuzugreifen
In JavaScript ist der ausführbare JavaScript -Code in drei Typen unterteilt:
1. Globaler Code, dh globaler Code, der sich in keiner Funktion befindet, wie z.
2. Eval Code, dh JS -Code, der mit der Funktion eval () dynamisch ausgeführt wird.
3. Funktionscode, dh der Funktionsbody JS-Code in benutzerdefinierten Funktionen.
Überspringen Sie den Bewertungscode und sprechen Sie nur über die globale Ausführungsumgebung und die Funktionsausführungsumgebung.
1. Globales Umfeld:
Die globale Umgebung ist die am besten periphere Ausführungsumgebung. Die globale Ausführungsumgebung wird als Fensterobjekt angesehen. Daher werden alle globalen Variablen und Funktionen als Eigenschaften und Methoden von Fensterobjekten erstellt. Wenn der Code in den Browser geladen wird, wird die globale Ausführungsumgebung erstellt (die globale Ausführungsumgebung wird nur zerstört, wenn wir die Webseite oder den Browser schließen). Erstellen Sie beispielsweise auf einer Seite eine globale Ausführungsumgebung, wenn JS Code zum ersten Mal geladen wird.
Dies ist auch der Grund, warum Verschlüsse einen Speicher -Leck -Nachteil haben. Weil externe Funktionen bei Schließungen als globales Umfeld behandelt werden. Es wird also nicht zerstört und wird in Erinnerung bleiben.
2. Funktionsausführungsumgebung
Jede Funktion hat eine eigene Ausführungsumgebung. Wenn die Ausführung in eine Funktion eingeht, wird die Ausführungsumgebung der Funktion auf einen Ausführungsumfeldstapel gedrängt und die Ausführungsrechte erhalten. Wenn diese Funktion ausgeführt wird, wird die Ausführungsumgebung von der Spitze des Stapels gelöscht und das Ausführungsrecht in die vorherige Ausführungsumgebung zurückgegeben. Dies ist der Ausführungsfluss im ECMascript -Programm.
Es kann auch auf diese Weise interpretiert werden: Wenn eine JavaScript -Funktion aufgerufen wird, gilt die Funktion in die Ausführungsumgebung, die der Funktion entspricht. Wenn eine andere Funktion aufgerufen wird, wird eine neue Ausführungsumgebung erstellt, und der Ausführungsprozess befindet sich während des Funktionsaufrufs in dieser Umgebung. Wenn die aufgerufene Funktion zurückgibt, kehrt der Ausführungsprozess in die ursprüngliche Ausführungsumgebung zurück. Das Ausführen von JavaScript -Code bildet daher einen Ausführungsumfeldstapel.
Wenn eine Funktion aufgerufen wird, wird die lokale Umgebung der Funktion erstellt (nachdem der Code in der Funktion ausgeführt wurde, wird die Umgebung zerstört und alle in IT gespeicherten Variablen und Funktionsdefinitionen werden ebenfalls zerstört).
2-1 Definitionsperiode
Wenn eine Funktion definiert ist, wird ein [[Scope]] -Triput erstellt. Dieses Objekt entspricht einer Liste von Objekten. Die Objekte in der Liste können nur von JavaScript intern zugegriffen werden und können nicht über Syntax zugegriffen werden.
(Umfang bedeutet Umfang.)
Wir definieren eine globale Funktion A, und dann erstellt die A -Funktion das Attribut eines A [[Scope]]. Zu diesem Zeitpunkt enthält [[Scope]] nur das globale Objekt [globales Objekt].
Wenn wir eine Funktion B in A definieren, erzeugt die Funktion B auch ein [[Scope]] -Triput. Bs [[Scope]] Attribut enthält zwei Objekte, eines ist das aktive Objektaktivierungsobjekt des aktiven Objekts A und das andere ist das globale Objekt. Das aktive Objekt von A befindet sich vorne und das globale Objekt befindet sich hinten.
Kurz gesagt, die Reihenfolge der Objektliste in der Eigenschaft [Scope] einer Funktion ist das Aktivierungsobjektobjekt der vorherigen Funktionsschicht und dann die obere Schicht bis zum äußersten globalen Objekt.
Hier ist der Beispielcode: A hat nur einen Umfang, B hat zwei Bereiche
// externe Funktionsfunktion a () {var irgendwann; // Innere Funktion Funktion b () {var selten; }}2-2 Ausführungsperiode
Wenn eine Funktion ausgeführt wird, tritt sie in die Ausführungsumgebung der Funktion ein. Zunächst schafft es ein eigenes aktives Objekt [Aktivierungsobjekt] (dieses Objekt enthält die Definition dieser, Argumente, lokale Variablen (einschließlich der benannten Parameter) und eine Bereichskette eines variablen Objekts. Dann kopieren Sie den Umfang der Ausführungsumgebung in [[Scope -Kette]] in der Reihenfolge und schieben schließlich das aktive Objekt in die Spitze der Gründungskette. und Objekte, die die Erlaubnis haben, auf die Ausführungsumgebung zuzugreifen.
// Der erste Schritt besteht darin, die globale Ausführungsumgebung zu schaffen. Globaler Ausführungskontext und globale Aktivitätsobjekte. // Definieren Sie die globale [[Scope]], die nur Fensterobjekte enthält // die globalen Definitionsvariablen und Funktionsobjekte: Farbe 【undefiniert】, ChangeColor 【FD erzeugt ChangeColor [[Scope]], die nur globale Aktivitätsobjekte enthält, die zum Fenster definiert sind, sodass die globalen Variablen und globale Funktionsobjekte definiert sind, die als Eigenschaften des Fensters definiert sind. // Das Programm wurde definiert, sodass ChangeColor () überall in dieser Ausführungsumgebung ausgeführt werden kann. Die Farbe wurde ebenfalls definiert, aber sein Wert ist undefiniert // Der zweite Schritt ist die Farbe "blau" var color = "blau"; // Es erfordert keine Zuordnung, sie bezieht sich auf seine eigene Funktion echnamecolor () {// Der vierte Schritt tritt in die Ausführungsumgebung von Aechsecolor // kopieren Sie die echscolor- und definierte Variable. Ein anderer Color 【undefined】 und Swapcolors 【fd erstellt die SwapColors [[Scope]] und fügen die aktiven Objekte und globalen aktiven Objekte zu den aktiven Objekten hinzu und fügen auch Argumente hinzu, und diese // Die aktiven Objekte drücken in die Top // die Top // Die Swapcolors () können in dieser Umwelt überall ausgeführt werden. Ein weiterer Anhaltspunkt wurde definiert, aber sein Wert ist undefiniert // die fünfte andere Color -Zuordnung "rot" var AnotherColor = "Red"; // Es erfordert keine Zuordnung, es bezieht sich auf seine eigene Funktion swapcolors () {// Schritt 7 Geben Sie die Ausführungsumgebung von Swapcolors ein und erstellen Sie sein aktives Objekt // Swapcolors '[Scope]], um zu definieren, um Variablen zu definieren und Funktionsobjekte zu definieren. Tempcolor -Zuordnungswert eines anderen Colors, einem anderen Color und einer anderen Farbe werden entlang der Umfangskette gefunden und führen weiterhin VAR tempcolor = ein anderes Color aus; AnotherColor = Farbe; color = tempcolor; } // Schritt 6: Führen Sie Swapcolors aus und geben Sie seine Ausführungsumgebung Swapcolors ();} // Schritt 3: Führen Sie die ChangeColor aus und geben Sie seine Ausführungsumgebung echrCOLOR () ein.2-3 Zugangskennung:
Wenn während der Ausführung des JS -Code eine Kennung auftritt, wird in der Umfangskette des Ausführungskontexts (Ausführungskontext) basierend auf dem Namen der Kennung durchsucht. Suchen Sie nach dem ersten Objekt der Bereichskette (das Aktivierungsobjekt der Funktion), wenn sie nicht gefunden wird, nach dem nächsten Objekt in der Bereichskette und wiederholen Sie, bis die Identifikatordefinition gefunden wird. Wenn das letzte Objekt im Bereich nicht nach der Suche nach der Suche gefunden wird, dh das globale Objekt (globales Objekt), wird ein Fehler geworfen, der undefiniertes Auftrag.
2. Umfang/Umfangskette (Bereichsbereich/Umfangskette)
Wenn der Code in einer Umgebung ausgeführt wird, wird eine Scope -Kette erstellt. Der Zweck der Bereichskette ist es, den geordneten Zugriff auf alle Variablen und Funktionen zu gewährleisten, die die Erlaubnis zum Zugriff auf die Ausführungsumgebung haben. Die gesamte Umfangskette ist eine verknüpfte Liste, die von variablen Objekten an verschiedenen Ausführungsorten gemäß den Regeln erstellt wurde. Das vordere Ende der Bereichskette ist immer das variable Objekt in der Umgebung, in der sich der derzeit ausgeführte Code befindet.
Wenn diese Umgebung eine Funktion ist, wird sein Aktivierungsobjekt als variables Objekt verwendet. Das aktive Objekt enthält nur eine Variable am Anfang, das das Argumenteobjekt in der Funktion ist. Das nächste variable Objekt in der Bereichskette stammt aus der Einschlussumgebung der Funktion, und das nächste variable Objekt stammt aus der nächsten Einschlussumgebung. Auf diese Weise setzt es die globale Ausführungsumgebung fort, und das variable Objekt der globalen Ausführungsumgebung ist immer das letzte Objekt in der Bereichskette.
Wie in der Abbildung gezeigt:
Beispiele im Buch:
var color = "blau"; function echnecolor () {var AnotherColor = "rot"; function swapcolors () {var tempcolor = AnotherColor; AnotherColor = Farbe; color = tempcolor; // etwas} swapcolors ();} ChangeColor (); // Tempcolor und Anocolor können hier nicht zugegriffen werden; Aber Farbe kann zugegriffen werden; alarm ("Farbe ist jetzt"+Farbe);Durch die obige Analyse können wir wissen, dass die interne Umgebung über den Bereichsketten auf alle externen Umgebungen zugreifen kann, aber die externe Umgebung kann in der internen Umgebung nicht auf Variablen und Funktionen zugreifen.
Diese Umgebungen sind linear und ordentlich. Jede Umgebung kann nach oben nach oben nach oben suchen, um Variablen und Funktionsnamen zu abfragen. Jede Umgebung kann jedoch keine andere Ausführungsumgebung betreten, indem nach Ablauf der Zielfernrohrketten gesucht werden.
Für die Funktion von SWAPCOLOR () im obigen Beispiel umfasst seine Bereichskette: SWAPCOLOR () Variable -Objekt, Variablenobjekt echnecolor () und globales Objekt. Die lokale Umgebung von swapcolor () beginnt, nach Variablen und Funktionsnamen in seinem eigenen Variablenobjekt zu suchen. Wenn es nicht gefunden werden kann, suchen Sie nach der ChangeColor Scope -Kette nach oben. . . . . Und so weiter. Die Funktion "echnecolor () kann jedoch in Swapcolor nicht auf Variablen zugreifen
Offenbarung: Versuchen Sie, lokale Variablen zu verwenden, um die Suchzeit zu verkürzen
1. Kein Umfang auf Blockebene
Im Gegensatz zu C, C ++ und Java hat JavaScript keinen Umfang auf Blockebene. Schauen Sie sich den folgenden Code an:
if (true) {var myvar = "zhang san"; } alarm (myvar); // Zhang SanWenn es einen Umfang auf Blockebene gibt, kann MyVar von außen nicht zugegriffen werden. Schauen Sie sich die folgenden an
für (var i = 0; i <10; i ++) {console.log (i)} alert (i); // 10Für Sprachen mit Blockebene wie Java oder C# Code ist ich eine variable initialisierte und kann außerhalb von außerhalb von außen zugegriffen werden. Weil ich nach dem Ausführen der für die Loop nur im für die für die Schleifen ausgeführten für Schleifen existiert, werden alle Variablen in die für zerstört. Dies ist in JavaScript nicht der Fall. Die variable Deklaration in wird in die aktuelle Ausführungsumgebung hinzugefügt (hier ist die globale Ausführungsumgebung). Daher, nachdem die für die für die Schleife abgeschlossene Schleife abgeschlossen ist, gibt es die Variable, die ich in der Ausführungsumgebung außerhalb der Schleife noch vorhanden ist. Daher wird 10 ausgegeben.
2. Variablen deklarieren
Wenn eine Variable mit VAR deklariert wird, wird diese Variable automatisch zur nächsten verfügbaren Umgebung hinzugefügt. Für die Innenseite einer Funktion ist die engste Umgebung die lokalen Variablen der Funktion. Wenn die Variable nicht initialisiert wird, wird die Variable automatisch zur globalen Funktion hinzugefügt.
Der Code ist wie folgt:
var name = "xiao ming"; Funktion getName () {alert (name); // 'undefined' var name = 'xiao huang'; alarm (Name); // xiao huang} getName ())Warum ist der Vorname undefiniert? Dies liegt daran, dass der JavaScript -Parser in eine Funktionsausführungsumgebung eingeht und zuerst var und Funktion scannt.
Es entspricht der Förderung der Deklaration von VaR oder Funktion [Funktionserklärung] an die Spitze der Ausführungsumgebung.
Mit anderen Worten, beim Eingeben unserer GetName -Funktion findet der Identifikator -Suchmechanismus den VAR, und der Name ist der lokale Variablenname, nicht der globale Name, da der Name in der Funktion nach oben befördert wird.
Der obige Code wird wie folgt analysiert:
var name = "xiao ming"; Funktion getName () {var name; alarm (Name); // 'undefined' var name = 'xiao huang'; alarm (Name); // xiao huang} getName ())Erweitern Sie die Bereichskette:
Obwohl es nur zwei Arten von Ausführungsumgebungen gibt - globaler Umfang und funktionaler Umfang, kann die Bereichskette noch in irgendeiner Weise erweitert werden. Da einige Aussagen ein temporäres variables Objekt zur Oberseite der Bereichskette hinzufügen können.
Es gibt zwei Situationen, in denen dies geschieht:
1. Der Fangblock der Anweisung Try-Catch;
2. mit Aussage;
Das obige dreht sich alles um diesen Artikel. Ich hoffe, es wird für alle hilfreich sein, die Umgebung und den Umfang der JavaScript -Ausführung zu lernen und zu verstehen.