Zusammenfassung des JS-Ausführungskontexts und -umfangs

Zusammenfassung des JS-Ausführungskontexts und -umfangs

Vorwort

Wenn Sie ein qualifizierter Front-End-Entwickler sind oder werden möchten, müssen Sie den Ausführungsprozess von JavaScript-Code kennen, den Ausführungskontext, den Umfang, die Variablenförderung und andere verwandte Konzepte kennen und diese geschickt auf Ihren eigenen Code anwenden. Dieser Artikel bezieht sich auf „JavaScript, das Sie nicht kennen“, „Erweiterte JavaScript-Programmierung“ und einige Blogs.

Text

1. Konzepte im Zusammenhang mit dem Ausführungsprozess von JavaScript-Code

Die Ausführung von JS-Code ist in zwei Phasen unterteilt: Compiler-Kompilierung und JS-Engine- und Bereichsausführung. Die Compiler-Kompilierungsphase (Vorkompilierungsphase) ist in drei Phasen unterteilt: Wortsegmentierung/lexikalische Analyse, Parsing/syntaktische Analyse und Codegenerierung.

(1) In der Phase der Wortsegmentierung/lexikalischen Analyse ist der Compiler für die Segmentierung des Codes und die Aufteilung der Anweisungen in lexikalische Einheitsströme/Arrays verantwortlich.

(2) In der Parsing-/Lexikalanalysephase wird der lexikalische Einheitenstrom der vorherigen Phase in einen abstrakten Syntaxbaum umgewandelt, der aus verschachtelten Elementen besteht, die der grammatikalischen Struktur des Programms entsprechen.

(3) In der Codegenerierungsphase wird der abstrakte Syntaxbaum in ausführbaren Code umgewandelt und an die JS-Engine übermittelt.

Drei wichtige Rollen der JS-Codeausführung:

(1) JS-Engine: verantwortlich für den gesamten Prozess der Codeausführung

(2) Compiler: verantwortlich für die Analyse der JS-Codesyntax und die Generierung von ausführbarem Code

(3) Geltungsbereich: Erfassen und Verwalten aller deklarierten Kennungen und Festlegen der Zugriffsrechte des aktuellen Codes auf die deklarierten Kennungen nach bestimmten Regeln.

2. Ausführungskontext und Ausführungsstapel

Immer wenn JavaScript-Code ausgeführt wird, wird er in einem Ausführungskontext ausgeführt. Wenn es um den Ausführungskontext geht, müssen Sie wissen, was der Ausführungsstapel ist. Der Ausführungsstapel, der in anderen Programmiersprachen der „Aufrufstapel“ ist, ist ein Stapel mit einer LIFO-Datenstruktur (Last In, First Out), der zum Speichern des Ausführungskontexts verwendet wird, der beim Ausführen des Codes erstellt wird. Wenn die JS-Engine den auszuführenden Code zum ersten Mal findet, erstellt sie zunächst einen globalen Ausführungskontext und schiebt ihn in den aktuellen Ausführungsstapel. Immer wenn die Engine auf einen Funktionsaufruf stößt, erstellt sie einen neuen Ausführungskontext für die Funktion und schiebt ihn an den Anfang des Stapels. Die JS-Engine führt die Funktion am Anfang des Stapels aus. Wenn die Funktion ausgeführt wird, wird der Ausführungskontext vom Stapel entfernt und der Kontrollfluss erreicht den nächsten Kontext. Jeder Ausführungskontext enthält drei wichtige Eigenschaften: variables Objekt, Bereichskette und dies. Auch diese Eigenschaften müssen gründlich verstanden werden.

2.1 Kontextaufrufstapel

var scope1 = "globaler Bereich";
 Funktion checkscope1(){
 var scope1 = "lokaler Bereich";
 Funktion f(){
 konsole.log(Bereich1); 
 }
 Rückgabewert f();
 }
 Prüfumfang1();
var scope2 = "globaler Bereich";
 Funktion checkscope2(){
 var scope2 = "lokaler Bereich";
 Funktion f(){
 konsole.log(Bereich2);
 }
 Rückgabe f;
 }
 checkscope2()();

Beide der oben genannten Codeausschnitte geben lokalen Umfang aus

Im obigen Code muss der Gültigkeitsbereich eine lokale Variable sein. Sie können den Gültigkeitsbereich auf Blockebene finden. Unabhängig davon, wann und wo f() ausgeführt wird, ist diese Bindung immer noch gültig, wenn f() ausgeführt wird. Es tritt das gleiche Ergebnis auf, allerdings sind die Änderungen im Ausführungskontextstapel der beiden Codesegmente unterschiedlich:

Der erste Code: push(<checkscope1>functionContext)=>push(<f>functionContext)=>pop()=>pop()

Der zweite Code: push(<checkscope2>functionContext)=>pop()=>push(<f>functionContext)=>pop()

2.2 Drei Arten von Ausführungskontexten

(1) Globaler Kontext

Wenn die JS-Engine mit der Analyse des JS-Codes beginnt, stößt sie als Erstes auf den globalen Code. Während der Initialisierung wird ein globaler Ausführungskontext in den Aufrufstapel geschoben. Der Ausführungskontextstapel wird gelöscht, wenn die gesamte Anwendung beendet wird. Ganz unten im Stapel befindet sich immer der globale Ausführungskontext. Dies ist der standardmäßige oder grundlegende globale Gültigkeitsbereich. Der Code innerhalb jeder Funktion befindet sich im globalen Gültigkeitsbereich. Zuerst wird ein globales Fensterobjekt erstellt und dann wird dessen Wert auf den des globalen Objekts gesetzt. In einem Programm gibt es nur einen globalen Ausführungskontext. Im JS-Code der obersten Ebene können Sie damit auf das globale Objekt verweisen, da das globale Objekt der Kopf der Domänenkette ist, was bedeutet, dass alle nicht qualifizierten Variablen und Funktionen als Funktionen dieses Objekts abgefragt werden.

Kurz gesagt, es gibt nur einen globalen Ausführungskontext, der im Allgemeinen vom Browser im Client erstellt wird, nämlich das uns bekannte Fensterobjekt, und über dieses können wir direkt darauf zugreifen.

(2) Funktionskontext

Immer wenn eine Funktion aufgerufen wird, wird ein neuer Kontext für diese Funktion erstellt. Jede Funktion hat ihren eigenen Kontext, der beim Aufruf der Funktion erstellt wird. Es ist zu beachten, dass ein neuer Kontext erstellt wird, wenn dieselbe Funktion mehrmals aufgerufen wird.

(3) eval und mit Kontext

Innerhalb von eval und mit Funktionen ausgeführter Code verfügt ebenfalls über einen eigenen Ausführungskontext. Da JavaScript-Entwickler eval jedoch nicht sehr häufig verwenden, werde ich hier nicht näher darauf eingehen.

2.3 Phase der Erstellung des Ausführungskontexts

Die Erstellung des Ausführungskontexts ist in zwei Phasen unterteilt: Erstellungsphase und Ausführungsphase.

Die JS-Engine ist während der Erstellungsphase des Ausführungskontexts hauptsächlich für drei Dinge verantwortlich: Dies bestimmen ==> Erstellen einer lexikalischen Umgebungskomponente ==> Erstellen einer variablen Umgebungskomponente (ich verstehe es noch nicht ganz)

(1) Bestimmen Sie dies, was nicht im Detail erklärt wird

(2) Erstellen Sie eine lexikalische Umgebungskomponente

Eine lexikalische Umgebung ist ein Spezifikationstyp, der die Zuordnung von Bezeichnern zu bestimmten Variablen und Funktionen basierend auf der lexikalischen Verschachtelungsstruktur von ECMAScript-Code definiert. Eine lexikalische Umgebung besteht aus einem Umgebungsrekorder und einem möglicherweise leeren Wert, der auf eine äußere lexikalische Umgebung verweist. Der Umgebungsdatensatz wird verwendet, um den tatsächlichen Speicherort von Variablen und Funktionsdeklarationen in der aktuellen Umgebung zu speichern. Der Einführungsdatensatz für externe Umgebungen ist leicht zu verstehen. Er wird verwendet, um andere externe Umgebungen zu speichern, auf die von der eigenen Umgebung aus zugegriffen werden kann. Hat er in diesem Zusammenhang also eine gewisse Bedeutung für die Gültigkeitsbereichskette?

Es gibt zwei Arten von lexikalischen Umgebungen:

  • Die globale Umgebung (im globalen Ausführungskontext) ist eine lexikalische Umgebung, auf die keine äußeren Umgebungen verwiesen werden. Die äußere Umgebungsreferenz der globalen Umgebung ist null. Es verfügt über integrierte Objekte/Arrays/usw., Prototypfunktionen im Umgebungsrekorder (die mit dem globalen Objekt verknüpft sind, z. B. dem Fensterobjekt) und alle benutzerdefinierten globalen Variablen, und der Wert hiervon bezieht sich auf das globale Objekt.
  • In einer Funktionsumgebung werden benutzerdefinierte Variablen innerhalb einer Funktion im Umgebungsrekorder gespeichert. Bei der genannten äußeren Umgebung kann es sich um die globale Umgebung oder um eine beliebige äußere Funktion handeln, die diese innere Funktion enthält.

(3) Erstellen Sie variable Umgebungskomponenten

Die variable Umgebung kann auch als lexikalische Umgebung bezeichnet werden. Sie verfügt über alle Eigenschaften einer lexikalischen Umgebung und hat außerdem Umgebungsdatensätze und externe Umgebungseinführungen. Der einzige Unterschied in ES6 besteht darin, dass die lexikalische Umgebung zum Speichern von Funktionsdeklarationen und mit let const deklarierten Variablen verwendet wird, während die Variablenumgebung nur mit var deklarierte Variablen speichert.

3. JavaScript-Bereich und Bereichskette

3.1 Geltungsbereich

Der lexikalische Gültigkeitsbereich wird beim Schreiben oder Definieren von Code bestimmt, während der dynamische Gültigkeitsbereich zur Laufzeit bestimmt wird. (Dies ist auch der Fall.) Der lexikalische Gültigkeitsbereich konzentriert sich darauf, wo die Funktion deklariert wird, während der dynamische Gültigkeitsbereich sich darauf konzentriert, von wo aus die Funktion aufgerufen wird. JavaScript verwendet einen lexikalischen Gültigkeitsbereich, und sein Gültigkeitsbereich wird dadurch bestimmt, wo Sie beim Schreiben des Codes die Variablen und den Blockgültigkeitsbereich schreiben, sodass der Gültigkeitsbereich unverändert bleibt, wenn der lexikalische Analysator den Code verarbeitet. Man kann davon ausgehen, dass der Umfang ein unabhängiges Gebiet ist, das das Durchsickern oder die Offenlegung von Variablen verhindert. Mit anderen Worten, der größte Nutzen des Bereichs besteht in der Isolierung von Variablen, und es kommt nicht zu Konflikten zwischen Variablen mit demselben Namen in unterschiedlichen Bereichen.

Schauen wir uns eine Frage an, bevor wir den Umfang verstehen

Funktion foo() {
 konsole.log(Wert);
 }
 Var-Wert = 1;
 Funktion bar() {
 Var-Wert = 2;
 konsole.log(Wert);
 foo();
 }
 Bar();

Was gibt der obige Code aus? Zuerst werden die Funktion foo(), die Variable value (deren Wert nicht definiert ist) und die Funktion bar() im globalen Kontext deklariert. Während der Codeausführungsphase wird der Kontext der Funktion bar auf den Stapel geschoben und ausgeführt, und der Wert wird als 2 ausgegeben. Dann wird foo() ausgeführt und foo() auf den Stapel geschoben. Beim Drucken des Werts kann die Variable nicht gefunden werden, daher sucht die JS-Engine nach dem oberen Bereich, also dem globalen Bereich, und gibt 1 aus. Nachdem die Funktion ausgeführt wurde, wird der Kontext aus dem Stapel entfernt. Schauen wir uns die folgende Funktion an. Der Gültigkeitsbereich ist mehrschichtig. Der innere Gültigkeitsbereich kann auf die Variablen des äußeren Gültigkeitsbereichs zugreifen, aber nicht umgekehrt.

Seit ES6 werden die Bereiche in js in globalen Bereich, Funktionsumfang, Blockbereich und Täuschungsbereich unterteilt.

3.1.1 Globaler Geltungsbereich

Objekte, auf die von überall im Code zugegriffen werden kann, haben einen globalen Gültigkeitsbereich, die äußerste Funktion und Variablen, die außerhalb der äußersten Funktion definiert sind, haben einen globalen Gültigkeitsbereich und alle undefinierten und direkt zugewiesenen Variablen werden automatisch als Variablen mit globalem Gültigkeitsbereich deklariert.

3.1.2 Funktionsumfang

Funktionsumfang bedeutet, dass alle zu dieser Funktion gehörenden Variablen innerhalb des Umfangs der gesamten Funktion verwendet und wiederverwendet werden können (tatsächlich können sie auch in verschachtelten Bereichen verwendet werden).
Dieses Prinzip bedeutet, dass beim Softwaredesign die notwendigen Inhalte so wenig wie möglich sichtbar gemacht werden sollten, während andere Inhalte „versteckt“ werden sollten.
Funktionsausdrücke können anonym sein, aber Funktionsdeklarationen dürfen den Funktionsnamen nicht weglassen.
3.1.3. Blockbereich Der Blockbereich bezieht sich normalerweise auf die { .. } innerhalb
(1) wenn ja, try/catch, um den Blockbereich zu erstellen;
(2) Das Schlüsselwort let kann eine Variable an jeden beliebigen Bereich binden (normalerweise innerhalb von { .. } );
(3) Das Let am Anfang der For-Schleife bindet i nicht nur an den For-Schleifenblock, sondern bindet es tatsächlich bei jeder Iteration der Schleife erneut an und stellt so sicher, dass ihm am Ende der vorhergehenden Schleifeniteration der Wert neu zugewiesen wird.
(4) Mit const können auch Variablen mit Blockbereich erstellt werden, deren Werte jedoch fest sind (Konstanten). Der Wert kann beim Erstellen des Objekts geändert werden.
3.1.4. Methoden zum Austricksen des lexikalischen Gültigkeitsbereichs, eval() und with()
Der Parameter eval() ist eine Zeichenfolge und der Inhalt wird wie der an dieser Stelle geschriebene Code behandelt (nicht strikter Modus).
Wenn Sie mit() wiederholt auf mehrere Eigenschaften eines Objekts verweisen müssen, müssen Sie nicht wiederholt auf das Objekt selbst verweisen.

3.2 Geltungsbereichskette

Bei der Bereichskette handelt es sich im Wesentlichen um einen Regelsatz zum Nachschlagen von Variablen (Bezeichnernamen) anhand des Namens. Die Regel ist ganz einfach. Wenn eine Variable nicht in ihrem eigenen Variablenobjekt gefunden werden kann, wird im übergeordneten Variablenobjekt gesucht. Wenn sie den äußersten globalen Kontext erreicht, wird der Suchvorgang beendet, unabhängig davon, ob sie gefunden wird oder nicht. Die Suche wird beendet, wenn die erste passende Variable gefunden wird. Dies wird als Shadowing bezeichnet.

Der Zweck der Bereichskette besteht darin, einen geordneten Zugriff auf alle Variablen und Funktionen sicherzustellen, auf die die Ausführungsumgebung Zugriff hat.
Bereichskette: Wenn eine Funktion definiert wird, generiert das System ein ([scope])-Attribut, das die Bereichskette der Funktion speichert. Das 0. Bit der Bereichskette speichert den globalen Ausführungskontext GO in der aktuellen Umgebung. GO speichert alle globalen Objekte, einschließlich Funktionen und globaler Variablen. Wenn die Funktion vor der Ausführung vorkompiliert wird, speichert das obere Ende der Bereichskette (0. Bit) den von der Funktion generierten Ausführungskontext AO und das erste Bit speichert GO.
Um nach einer Variablen zu suchen, beginnen Sie oben in der Bereichskette, in der die Funktion gespeichert ist, und suchen nach unten (der Bereich innerhalb der Funktion befindet sich oben, was beweist, dass die Funktion auf externe Variablen zugreifen kann, von außen jedoch nicht auf die Variablen innerhalb der Funktion).

4. Der Unterschied zwischen Ausführungskontext und Umfang

Jedem Funktionsaufruf ist ein Gültigkeitsbereich und ein Kontext zugeordnet. Der Umfang ist grundsätzlich funktionsbasiert und der Kontext objektbasiert. Mit anderen Worten: Der Gültigkeitsbereich bestimmt, wie bei jedem Funktionsaufruf auf Variablen zugegriffen wird, und jeder Aufruf ist unabhängig. Der Kontext ist immer der Wert des Schlüsselworts this, welches eine Referenz auf das Objekt darstellt, das den aktuell ausführbaren Code aufgerufen hat. Der Umfang wird bei der Definition der Funktion festgelegt. Die Variablen in der Funktion beziehen sich auf den Umfang der Funktion, und der Umfang, in dem die Funktion ausgeführt wird, bezieht sich auch auf den Umfang bei der Definition der Funktion. Der Kontext bezieht sich hauptsächlich auf den Wert des Schlüsselworts this, der beim Ausführen der Funktion bestimmt wird. Einfach ausgedrückt bezieht sich this auf denjenigen, der diese Funktion aufruft.

5. Zuletzt

Oben finden Sie eine detaillierte Zusammenfassung des Ausführungskontexts und -umfangs von JS. Weitere Informationen zum Ausführungskontext und -umfang von JS finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Fortgeschrittene JavaScript-Programmierung: Variablen und Umfang
  • Grafische Erklärung des zugrunde liegenden Prinzips der JavaScript-Bereichskette
  • Statischer und dynamischer Gültigkeitsbereich von JavaScript anhand von Beispielen erklärt
  • Javascript-Bereich und Abschlussdetails
  • Synchrone und asynchrone JS-Schwierigkeiten sowie Umfang und Abschluss und detaillierte Erklärung von Prototypen und Prototypenketten
  • Detaillierte Erklärung zur Verwendung von Scoped Slots in Vue.js-Slots
  • Gedanken und Austausch zu Umfangsproblemen in JS

<<:  Tutorial zum Kompilieren und Installieren von MySQL 5.7.17 aus dem Quellcode auf dem Mac

>>:  Beispiel für die Verwendung von Docker Swarm zum Erstellen eines verteilten Crawler-Clusters

Artikel empfehlen

Implementierung der MySQL-Datensortierung (aufsteigend und absteigend)

Datensortierung aufsteigend, absteigend 1. Sortie...

Details zur Überwachung von DOM-Elementen durch MutationObServer in JavaScript

1. Grundlegende Verwendung Es kann über den Mutat...

JavaScript generiert zufällige Grafiken durch Klicken

In diesem Artikel wird der spezifische Code von J...

Detaillierte Erklärung des Befehlsmodus in der Javascript-Praxis

Inhaltsverzeichnis Definition Struktur Beispiele ...

So erstellen Webdesigner Bilder für Retina-Displays

Besonderer Hinweis: Dieser Artikel wurde basieren...

Lösung zum Ändern des Datenspeicherorts der Datenbank in MySQL 5.7

Da die in der MySQL-Datenbank gespeicherten Daten...

Tabelle zeigt den Grenzcode, den Sie anzeigen möchten

Gemeinsame Eigenschaften von Tabellen Die grundle...

Detaillierte Erklärung des Linux-Befehls unzip

Inhaltsverzeichnis 1. Unzip-Befehl 1.1 Syntax 1.2...

Tutorial zur Master-Slave-Konfiguration der MySQL-Datenbank unter Windows

Der detaillierte Prozess zum Konfigurieren des My...

Vue-Entwicklungsbaumstrukturkomponenten (Komponentenrekursion)

In diesem Artikelbeispiel wird der spezifische Co...

Anwendungshandbuch für chinesische WEB-Schriftarten

Die Verwendung von Schriftarten im Web ist sowohl ...

MySQL zeigt ein einfaches Operationsbeispiel

Dieser Artikel beschreibt den MySQL-Show-Vorgang ...

So überprüfen und organisieren Sie Websitedateien mit Dreamweaver8

Was ist der Zweck der Erstellung einer eigenen Web...