Heim  >  Artikel  >  Web-Frontend  >  Beherrschen Sie den JavaScript-Vorkompilierungsprozess vollständig

Beherrschen Sie den JavaScript-Vorkompilierungsprozess vollständig

WBOY
WBOYnach vorne
2022-02-10 17:57:231758Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über die Vorkompilierung in Javascript. Er stellt hauptsächlich Probleme im Zusammenhang mit der Vorkompilierung anhand von Beispielen vor.

Beherrschen Sie den JavaScript-Vorkompilierungsprozess vollständig

Phasen (drei)

  1. Lexikalische und syntaktische Analyse: Bei der lexikalischen und syntaktischen Analyse wird überprüft, ob der JavaScript-Code einige grammatikalische Fehler auf niedriger Ebene aufweist.
  2. Vorkompilierung: Das Hauptthema dieses Artikels.
  3. Ausführung Code: Der Ausführungscode ist der Parsing-Code der js-Engine. Analysieren Sie eine Zeile und führen Sie eine Zeile aus. In diesem Kapitel geht es hauptsächlich um den
  4. Vorkompilierungsprozess, den Vorkompilierungsprozess und die Vorkompilierung Zeitpunkte:

Der erste ist, bevor der JavaScript-Code ausgeführt wird

Der zweite ist, bevor die Funktion ausgeführt wird.

  1. Aber vor dem JavaScript-Code erfolgt die vorherige Vorkompilierung nur einmal, und die Vorkompilierung vor der Funktionsausführung erfolgt mehrmals.
  2. 1. Vorkompilierung vor der Ausführung des JavaScript-Codes
Bevor der JavaScript-Code ausgeführt wird, wird zunächst ein globales Objekt erstellt, das als window-Objekt oder als

GO( Global Object) Objekt, wir können es nicht sehen (kann nicht drucken)

Dann werden alle deklarierten

globalen Variablen

,
    unused var und let Die Variablen deklariert by code> werden im GO-Objekt platziert und der Wert ist <code>undefiniert (erinnert an „Variablenförderung“)
  1. window对象,也可以理解为GOGlobal Object)对象,我们是看不到的(无法打印)
  2. 然后将所有声明的全局变量未使用varlet声明的变量放到GO对象中,并且赋值为undefined(联想到“变量提升”)
  3. 分析**函数声明:**然后再将所有的函数声明也放到GO对象中,并且赋值为函数自身的函数体(函数名为属性名,值为函数体,如果函数名和变量名相同,则无情覆盖)

案例说明

<script>
    var a = 1;
    console.log(a);
    console.log(b);
    var b = 10;
    function fun (a) {
        console.log(b);
        var a = b = 2;
        var c = 123;
        console.log(a);
        console.log(b);
    }
    var a2 = 20
    fun(1);
 
</script>

结合上面说的步骤:

  1. 首先,<script></script>中的代码执行之前会创建一个GO对象(window对象)

    GO = {
    	//自带的属性都不写
    }
  2. 将所有声明的全局变量、未使用varlet声明的变量放到GO对象中,并且赋值为undefined

    GO = {
    	a : undefined,
    	b : undefined,
    	a2 : undefined
    }
  3. 分析函数声明,函数名为属性名,值为函数体,如果函数名和变量名相同,则无情覆盖

    GO = {
    	a : undefined,
    	b : undefined,
    	a2 : undefined,
    	function fun (a) {
        var a = b = 2;
        var c = 123;
      }
    }
  4. 此时完成了js代码执行之前的预编译过程,开始执行js代码,首先是给a进行赋值为1,在GO对象里边也会进行对应的改变:

    GO = {
    	a : 1,
    	b : undefined,
    	a2 : undefined,
    	function fun (a) {
        var a = b = 2;
        var c = 123;
      }
    }
  5. 然后打印a,此时会在GO对象上去找变量a,然后此时的a的值为1,所以console.log(a) 是等于1的。接着打印b,也会去GO对象上找,找到了b的值为undefined,所以console.log(b)是等于undefined

  6. 接着执行到赋值语句:b = 10; 此时GO对象里b的值变成了10

    GO = {
    	a : 1,
    	b : 10,
    	a2 : undefined,
    	function fun (a) {
    		var a = b = 2;
    		var c = 123;
    	}
    }
  7. 接着下一行代码是一个**fun函数,此时不会去执行该函数**,因为在前面的预编译过程中实际上是被放到了代码的最前端,就是传说中的声明提前,所以忽略掉了。接着给a2进行赋值操作a2 = 20,GO对象也发生变化:

    GO = {
    	a : 1,
    	b : 10,
    	a2 : 20,
    	function fun (a) {
    		var a = b = 2;
    		var c = 123;
    	}
    }
  8. 接着是执行fun函数,如上面说到的另外一个时间点发生的预编译,就是执行函数之前,现在就来说一下函数执行前的预编译是怎么样的。

2. 函数执行前的预编译

  1. 函数调用,也是会生成自己的作用域(**AO:**Activetion Object,执行期上下文)AO活动对象。函数调用时候,执行前的一瞬间产生的,如果有多个函数的调用,会产生多个AO

    1. 生成AO对象:函数执行前的一瞬间,生成AO活动对象
    2. 分析生成AO属性:查找形参变量声明放到AO对象,赋值为undefined
    3. 分析函数声明:查找函数声明放到AO对象并赋值为函数体。函数名为属性名,值为函数体;

    如果遇到AO对象上属性同名,则无情覆盖

  2. 逐行执行。

案例说明

拿的是上文中的代码示例。

  1. 第一步创建AO对象

    AO{
    
    }
  2. 查找形参变量声明放到AO对象并赋值为undefined

    注意:fun函数里边的b是未经var声明的,所以是全局变量,不会被放在funAnalysieren Sie die ** Funktionsdeklaration: ** Fügen Sie dann auch alle Funktionsdeklarationen hinzu das GO-Objekt und weisen Sie den Wert dem Funktionskörper der Funktion selbst zu (

    Der Funktionsname ist der Attributname und der Wert ist der Funktionskörper. Wenn der Funktionsname und der Variablenname identisch sind, werden sie gnadenlos überschrieben
    )
  3. Fallbeschreibung

    AO{
    	a: undefined,//形参a与局部变量a同名
    	c: undefined
    }

    Kombiniert mit den oben genannten Schritten: Zuerst, bevor der Code in <script></script> ausgeführt wird , ein GO-Objekt (Fensterobjekt) wird erstellt

    AO{
    	a: 1,
    	c: undefined,
    }
  4. werden alle deklarierten globalen Variablen und Variablen, die nicht mit var und let deklariert wurden, im GO-Objekt platziert, und der Wert wird undefiniert

    GO = {
    	a : 1,
    	b : 10,
    	a2 : 20,
    	function fun (a) {
    		var a = b = 2;
    		var c = 123;
    	}
    }
    🎜🎜🎜Analyse 🎜Funktionsdeklaration🎜 zugewiesen, der Funktionsname ist der Attributname und der Wert ist der Funktionskörper Ebenso werden sie gnadenlos überschrieben🎜
    AO{
    	a: 2,
    	c: undefined,
    }
    🎜🎜🎜Zu diesem Zeitpunkt ist der Vorkompilierungsprozess vor der Ausführung des JS-Codes abgeschlossen und die Ausführung des JS-Codes beginnt zuerst 🎜, und die entsprechenden Änderungen werden im GO-Objekt vorgenommen: 🎜
    AO{
    	a: 2,
    	c: 123,
    }
    🎜🎜🎜 Dann wird a gedruckt. Zu diesem Zeitpunkt wird die Variable a im GO-Objekt gefunden und der Wert von a beträgt zu diesem Zeitpunkt 1. also ist console.log(a) gleich 1. Wenn dann b gedruckt wird, wird auch nach dem GO-Objekt gesucht, und der Wert von b ist undefiniert, sodass console.log(b) gleich undefiniert ist. Code>. 🎜🎜🎜🎜Dann wird die Zuweisungsanweisung ausgeführt: <code>b = 10; Zu diesem Zeitpunkt wird der Wert von 🎜b im GO-Objekt zu 10🎜🎜rrreee🎜🎜🎜Dann ist die nächste Codezeile Eine **fun-Funktion, diese Funktion wird zu diesem Zeitpunkt nicht ausgeführt**, da sie im vorherigen Vorkompilierungsprozess tatsächlich am vorderen Ende des Codes platziert wurde, was der Legende nach ist Deklaration im Voraus, also ignorieren Sie sie. Führen Sie dann die Zuweisungsoperation🎜 zu 🎜a2 aus: a2 = 20, und das GO-Objekt ändert sich ebenfalls: 🎜rrreee🎜🎜🎜Dann wird die Funktion fun wie oben erwähnt ausgeführt Die Vorkompilierung findet zu einem bestimmten Zeitpunkt statt, bevor die Funktion ausgeführt wird. 🎜🎜🎜🎜2. Vorkompilierung vor der Funktionsausführung🎜🎜🎜🎜Funktionsaufruf generiert auch einen eigenen Bereich (**AO: **Aktivierungsobjekt, Ausführungskontext)🎜AO🎜Aktivitätsobjekt. 🎜Wenn eine Funktion aufgerufen wird, wird sie im Moment vor der Ausführung generiert. Bei mehreren Funktionsaufrufen werden mehrere AOs generiert. 🎜🎜🎜🎜🎜 AO-Objekte generieren: Der Moment vor der Ausführung der Funktion, das AO-Aktivitätsobjekt 🎜🎜 wird generiert AO-Attribute analysieren und generieren 🎜: 🎜 formale Parameter 🎜 und 🎜 Variablendeklaration 🎜 finden und in das AO-Objekt einfügen, den Wert undefiniert zuweisen 🎜🎜🎜 Funktionsdeklaration analysieren 🎜: Suchen Sie die Funktionsdeklaration, fügen Sie sie in das AO-Objekt ein und weisen Sie sie als Funktionskörper zu. Der Funktionsname ist der Attributname und der Wert ist der Funktionskörper. 🎜🎜🎜🎜Wenn das Attribut mit demselben Namen auf dem AO-Objekt gefunden wird, wird es gnadenlos überschrieben 🎜🎜🎜🎜🎜 und Zeile für Zeile ausgeführt. 🎜🎜🎜

    Fallbeschreibung

    🎜Das obige Codebeispiel wurde übernommen. 🎜🎜🎜🎜🎜Der erste Schritt besteht darin, ein AO-Objekt zu erstellen blockquote>🎜Hinweis: fun
    wird nicht von var deklariert, daher ist es eine globale Variable und wird nicht auf dem AO von fun platziert. 🎜🎜rrreee🎜🎜🎜Weisen Sie den 🎜aktuellen Parameter🎜 dem 🎜formalen Parameter🎜🎜rrreee🎜🎜🎜 zu. Suchen Sie die Funktionsdeklaration, fügen Sie sie in das AO-Objekt ein und weisen Sie sie dem Funktionskörper zu. Ignorieren Sie diesen Schritt also. 🎜
  5. 函数执行之前的预编译完成,开始执行语句

  6. 执行代码

    1. 首先执行打印变量b,而此时fun的AO里边并没有变量b,所以会去GO对象里边找,此时的GO对象b的值为10,所以第一行代码打印出10;

    2. 第二行代码首先要看的是b = 2,然后GO对象里边b的值就被改为2了。

      GO = {
      	a : 1,
      	b : 10,
      	a2 : 20,
      	function fun (a) {
      		var a = b = 2;
      		var c = 123;
      	}
      }
    3. 然后b再赋值给a,变量a是属于局部变量a,所以fun的AO对象里边a的值被改为2。

      AO{
      	a: 2,
      	c: undefined,
      }
    4. 接着下一个赋值语句是c = 123,所以AO对象中c的值被改为了123

      AO{
      	a: 2,
      	c: 123,
      }
    5. 此时再执行console.log(a)的值就是AO对象里边a的值 2;执行console.log(b)的值就是GO对象b的值 2,至此函数fun执行完毕,紧跟着fun的AO也会被销毁

  7. 综上所述,依次打印出来的值为:1,undefined,10,2,2

总结

预编译两个小规则:

  1. 函数声明整体提升(无论函数调用和声明的位置是前是后,系统总会把函数声明移到调用前面)
  2. 变量声明提升(无论变量调用和声明的位置是前是后,系统总会把声明移到调用前,注意仅仅只是声明,所以值是undefined

预编译前奏

  1. imply global(暗示全局变量-专业术语) 即:任何变量,如果未经声明就赋值,则此变量就位全局变量所有。(全局域就是window,这里再一次说明了JavaScript是基于对象的语言,base on window)
  2. 一切声明的全局变量,全是window的属性;var a=12;等同于window.a = 12;(会造成window这个对象特别臃肿)
  3. 函数预编译发生在函数执行前一刻(懒加载机制)

相关推荐:javascript学习教程web前端开发视频教程

Das obige ist der detaillierte Inhalt vonBeherrschen Sie den JavaScript-Vorkompilierungsprozess vollständig. 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