javascript解析機制——預解析


JavaScript解析機制是什么?

  JavaScript解析過程分為兩個階段,一個是編譯階段,另外一個就是執行階段。

  * 編譯階段

         編譯階段就是我們常說的JavaScript預解析(預處理)階段,在這個階段JavaScript解釋器將完成把JavaScript腳本代碼轉換到字節碼。

  * 執行階段

    在編譯階段JavaScript解釋器借助執行環境把字節碼生成機械碼,並順序執行。

 

 

編譯階段(預解析階段)做什么操作?

  * var , function聲明的變量提升

    首先,創建一個當前執行環境下的活動對象,然后將用 var 聲明的變量設置為活動對象的屬性(也就是將其添加到活動對象當中)並將其賦值為undefined,然后將 function 定義的函數 也添加到活動對象當中。

1 if( false ){
2     var aa = 20;
3     var bb = 30;
4 }
5 
6 function AA(){};
7 function BB(){};
8 
9 //var定義的aa,bb以及function定義的AA(),BB()都會被變量提升到window對象下面

 

 

    * 函數聲明與函數表達式在預解析的區別

    首先,我們知道解析器會對function定義的函數(也就是函數聲明)在代碼開始執行之前對其實行函數聲明提升(function declaration hoisting),所以在函數聲明之前調用該函數是不會在執行期間報錯,但是函數表達式不同,函數表達式用 var 聲明,也就是說解析器會對其變量提升,並對其賦值為undefined,然后在執行期間,等到執行到該var 變量的時候再將其變量指向一個function函數,所以在函數表達式之前執行該函數是會報錯的。

1 AA();
2 function AA(){};
3 
4 BB();
5 var BB = function(){};
6 
7 //AA();不會報錯,因為是以function的變量提升,BB()會報錯,因為是以var的變量提升,到其相當於 BB(); var BB = undefined; BB = function(){};

 

  * function 覆蓋

    若定義了兩個同名的函數,則在預解析期間后面一個會覆蓋簽名一個

1 AA();   // 輸出 I am AA_2;
2 function AA(){
3    console.log('I am AA_1');
4 };
5 
6 AA();  // 輸出 I am AA_2;
7 function AA(){
8   console.log('I am AA_2');
9 }

 

  * 預解析把變量或函數解析到其運行時的環境中

    解析器將變量提升並不是將所有的變量都提升到window對象下面,其提升的原則是提升到變量運行的環境中去。

 1 aa = "I am aa";
 2 (function(){
 3     console.log(aa);  // 輸出 aa 是 undefined
 4     var aa = "I am aa in a function";
 5     console.log(aa);  //輸出 aa 是 I am aa in a function
 6 })();
 7 
 8 // 這里 aa 被變量提升,但是aa 沒有被變量提升到 window下面,而是被提升到其運行的環境 (function(){ })() 中去,也就是等同於
 9 
10 // aa =  "I am aa";
11 //(function(){
12 //    var aa;  
13 //    console.log(aa);  // 輸出 aa 是 undefined
14 //    aa = "I am aa in a function";
15 //    console.log(aa);  //輸出 aa 是 I am aa in a function
16 //})();
17 
18 
19 
20 // 下面代碼等同於上面,目的是為了若看不懂上面,則可看下面。
21 aa = "I am aa";
22 function AA(){
23     console.log(aa);
24     var aa = "I am aa in a function";
25     console.log(aa);
26 }
27 AA();

 

  * JavaScript“預解析”分段進行

    所謂分段進行是按照<script>標簽來分塊進行預解析

 1 <script>
 2 AA();  // 輸出 AA2;
 3 function AA(){
 4    console.log('AA1');
 5 }
 6 
 7 function AA(){
 8    console.log('AA2');
 9 }
10 </script>
11 
12 
13 <script>
14 function AA(){
15    console.log('AA3');
16 }
17 </script>
18 
19 //上面例子說明function函數聲明是分塊的,然而至於var變量的提升經過反復驗證是不分塊的( 此處如有不同意見請指教 )。

 

  * var 變量提升以及 function 函數聲明提升

    該點是對函數聲明以及函數表達式進一步的說明,其實前面函數聲明和函數表達式在預解析的不同表現,其主要的原因就是 var 和 function 兩者不同的提升。這個問題從解析階段到運行階段來說明。首先,在解析階段 var 后面的 AA 會被提升然后 AA 被定義為undefined,BB 也會被提升,而BB被提升后的內容就是整個 function 里面的內容,其實從瀏覽器的控制台我們可以看出一二。然后,整個解析過程完了就到了運行階段,在運行階段期間,當讀到 AA() 的時候,其實就是將 AA 這個變量指向function(){}這個函數然后調用,而到了 BB() 的時候,就會從之前聲明的函數中去查找該早已經聲明的函數,然后直接調用。

 1 var AA = function(){
 2    console.log(' AA_ 1 ');
 3 }
 4 
 5 AA(); // 輸出 AA_1
 6 
 7 
 8 function AA(){
 9    console.log(' AA_2 ');
10 }
11 AA(); //輸出 AA_2
12 
13 //這個例子就很好說明了 var 在運行階段動態內建,而 function 在預解析階段靜態建立。

 

    

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM