Heim  >  Artikel  >  Web-Frontend  >  Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt

Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt

WBOY
WBOYnach vorne
2022-03-29 11:49:391869Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über Javascript und stellt hauptsächlich die damit verbundenen Probleme vor, wie die JS-Engine JS-Code ausführt. Wenn die JS-Engine den JS-Code ausführt, führt sie auch eine lexikalische Analyse und Grammatikanalyse durch , semantische Analyse und andere Verarbeitungen und Generierung von AST nach Abschluss der Code-Analyse. Ich hoffe, dass dies für alle hilfreich ist.

Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt

Verwandte Empfehlungen: Javascript-Tutorial

Wir hören wahrscheinlich oft Dinge wie „Ausführungsumgebung“, „Umfang“, „Prototyp (Kette)“, „Ausführungskontext“ usw. Was beschreiben sie?

Ausführen von JS-Code

Wir wissen, dass JS eine schwach typisierte Sprache ist und der Variablentyp erst zur Laufzeit bestimmt wird. Wenn die js-Engine den js-Code ausführt, führt sie auch „lexikalische Analyse“, „grammatikalische Analyse“, „semantische Analyse“ und andere Prozesse von oben nach unten durch und generiert nach Abschluss der Codeanalyse einen AST (abstrakten Syntaxbaum). und schließlich basierend auf dem AST-Maschinencode generieren, den die CPU ausführen und ausführen kann. Darüber hinaus führt die JS-Engine beim Ausführen des Codes auch andere Verarbeitungen durch. Beispielsweise gibt es in V8 zwei Phasen: Kompilierungsphase: In dieser Phase wird der Ausführungskontext erstellt, einschließlich der Erstellung variabler Objekte (VO). Zu diesem Zeitpunkt wird es auf „undefiniert“ initialisiert, eine Bereichskette erstellt, dieser Punkt bestimmt usw. Jedes Mal, wenn Sie eine andere Betriebsumgebung betreten. V8 erstellt immer einen neuen Ausführungskontext.

Ausführungsphase: Schieben Sie den in der Kompilierungsphase erstellten Ausführungskontext in den Aufrufstapel und werden Sie zum laufenden Ausführungskontext. Nachdem der Code ausgeführt wurde, entfernen Sie ihn aus dem Aufrufstapel. (Hier gibt es einen VO-AO-Prozess: Die Variable wird verwendet, wenn JavaScript der Variablen einen Wert zuweist. Zu diesem Zeitpunkt wird das variable Objekt in ein aktives Objekt konvertiert und auf das konvertierte aktive Objekt kann zugegriffen werden)

    Dies führt zu zwei Konzepten: „Ausführungskontext“ und „Bereichskette“.
  • JavaScript-Ausführungskontext
Aus dem Obigen können wir wissen: Wenn js-Code einen ausführbaren Code ausführt, wird ein entsprechender Ausführungskontext erstellt.

Zunächst gibt es ein Konzept, das dem ausführbaren Code in js entspricht: „Ausführungsumgebung“ – globale Umgebung, Funktionsumgebung und

.
Zweitens gibt es für jeden Ausführungskontext drei wichtige Eigenschaften:

Variables Objekt (d. h. „VO“)
evalScope Chain

this
  • Schauen wir uns zwei Codeteile an:
  • var Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt="global Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt";function checkTiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt(){
    	var Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt="local Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt";
    	function f(){
    		return Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt;
    	}
    	return f();}checkTiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt();
    var Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt="global Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt";function checkTiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt(){
    	var Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt="local Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt";
    	function f(){
    		return Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt;
    	}
    	return f;}checkTiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt()();
  • Sie werden Was ausgeben ?

Warum? Die Antwort ist, dass ihre Ausführungskontextstapel unterschiedlich sind!


Was ist der „Ausführungskontextstapel“? Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt Bei der Ausführung eines ausführbaren Codes werden im Vorfeld Vorbereitungen getroffen. Die „Vorbereitungsarbeit“ wird hier professionell als „Ausführungskontext“ bezeichnet. Aber wie kann man angesichts der Zunahme von ausführbarem Code wie Funktionen so viele Ausführungskontexte verwalten? Daher hat die JS-Engine das Konzept des Ausführungskontextstapels entwickelt.

Wir können ein Array vollständig verwenden, um sein Verhalten zu simulieren (am Ende des Stapels befindet sich immer ein globaler Ausführungskontext globalContext).

Wir definieren zuerst einen EStack

EStack=[globalContext];

und simulieren dann den ersten Codeabschnitt:
EStack.push(<checktiefes verst daf wie die javascript-engine js-code ausf> functionContext);EStack.push(<f> functionContext);EStack.pop();EStack.pop();</f></checktiefes>
Und der zweite Teil des Codes sieht so aus:
EStack.push(<checktiefes verst daf wie die javascript-engine js-code ausf> functionContext);EStack.pop();EStack.push(<f> functionContext);EStack.pop();</f></checktiefes>

Der Grund dafür ist, dass Sie möglicherweise zuerst das Konzept des „Abschlusses“ studieren müssen!

Übrigens, wie implementiert man „Daten für lange Zeit speichern“ in der „Front-End-Modularisierung“?

Caching? NEIN. Schließung!

JavaScript Scope und Scope Chain


Der Bereich bezieht sich zunächst auf den Bereich im Programm, in dem Variablen definiert sind. Der Bereich gibt an, wie die Variable gefunden wird, wodurch die Zugriffsrechte des aktuell ausgeführten Codes auf die Variable bestimmt werden.

Es gibt zwei Arten von Bereichen:
statischer Bereich
und

dynamischer Bereich

.

Der von JS übernommene statische Bereich wird auch als „lexikalischer Bereich“ bezeichnet. Der Umfang einer Funktion wird bestimmt, wenn die Funktion definiert wird.
Aus dem oben Gesagten haben Variablen im lexikalischen Bereich während des Kompilierungsprozesses einen bestimmten Bereich. Dieser Bereich ist der „aktuelle Ausführungskontext“. Nach ES5 verwenden wir „lexikalische Umgebung“ anstelle von Bereich, um den Ausführungskontext zu beschreiben. Die lexikalische Umgebung besteht aus zwei Mitgliedern: Selbstlexikalische Umgebungsdatensätze: werden zum Aufzeichnen variabler Objekte in ihrer eigenen lexikalischen Umgebung verwendet.

Externe lexikalische Umgebungsreferenzen: werden zum Aufzeichnen von Referenzen verwendet, die in der äußeren lexikalischen Umgebung vorhanden sind. Wir sind immer noch hier Schauen Sie sich ein Beispiel an:

var value=1;function foo(){
	console.log(value);}function bar(){
	var value=2;
	foo();}bar();
Was soll im Rückblick auf die obige Definition gedruckt werden?
  • Lassen Sie uns den Ausführungsprozess analysieren:
Führen Sie die Funktion foo() aus und suchen Sie zunächst, ob in der Funktion foo ein lokaler Variablenwert vorhanden ist. Wenn nicht, sucht

nach dem Code der oberen Ebene

basierend auf der Position, an der er definiert wurde, d. h. Wert=1. Das Ergebnis wird also als 1 gedruckt.

Natürlich ist es nicht so einfach und kann aus der Perspektive des Ausführungskontexts zusammengefasst werden.

建立作用域链

上面我们说了词法环境(作用域)的两个组成。再结合执行上下文,我们不难发现:通过外部词法环境的引用,作用域可以顺着栈层层拓展,建立起从当前环境向外延伸的一条链式结构。

再来看一个例子:

function foo(){
	console.dir(bar);
	var a=1;
	function bar(){
		a=2;
	}}console.dir(foo);foo();

由静态作用域,全局函数foo创建了一个自身对象的 [[Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt]] 属性

foo[[Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt]]=[globalContext];

而当我们执行foo()时,也会先后进入foo函数的定义期和执行期。在foo函数的定义期时,函数bar的 [[Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt]] 将会包含全局内置Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt和foo的内置Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt

bar[[Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt]]=[fooContext,globalContext];

这证明了这一点:“JS会通过外部词法环境引用来创建变量对象的一个作用域链,从而保证对执行环境有权访问的变量和函数的有序访问。”

让我们再回头看看执行上下文中的那道题,在前面我们说了它们有什么不同,这里说下为什么它们相同地打印了“local Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt”:还是那句话“JS采用的是词法作用域,函数的作用域取决于函数创建的位置” —— JS函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量Tiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt一定是指局部变量,不管何时何地执行 f() ,这种绑定在执行 f() 时依然有效。

基于作用域链的变量查询

当某个变量无法在自身词法环境记录中找到时,可以根据外部词法环境引用向外层进行寻找,直到最外层的词法环境中外部词法环境引用为null
与此相似的是“对象中基于原型链的查找”:

  • 原型:每一个JS对象(null 除外)在创建时就会与另一个对象关联,这个对象就是我们说的原型。每一个对象都会从原型中“继承”属性。
  • 当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还找不到,就去找原型的原型,一直到最顶层(__proto__为null)为止

它们的区别也显而易见:原型链是通过 prototype 属性建立对象继承的链接;而作用域链是指内部函数能访问到外部函数的闭包。不管直接还是间接,所有函数的作用域链最终都链接到全局上下文。

相关推荐:javascript学习教程

Das obige ist der detaillierte Inhalt vonTiefes Verständnis dafür, wie die JavaScript-Engine JS-Code ausführt. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen