JS的解析與執行過程—(全局預處理階段)
阿新 • • 發佈:2019-03-06
調用 ont err col 過程 預處理 報錯 彈出 error:
問題:有如下代碼
1 var a = 1; 2 function pop() { 3 alert(a); 4 var a = 5; 5 } 6 pop();//執行結果,彈出undefined
這段代碼的執行結果為undefined,為什麽呢?
JS的解析與執行並不是讀一行,處理一行,讀一行,處理一行這樣進行的,而是分為兩個階段:
1、預處理階段;
2、執行階段;
然後分別以全局和函數內部的局部代碼而言:
1、全局預處理
在解析JS代碼的時候,首先會創建一個全局LexicalEnviroment{ }(詞法環境)對象
接下來掃描JS代碼裏面的兩個部分:
a、用聲明的方式創建的函數;
b、用var定義的變量;
掃面完畢後將這些變量及函數添加到全局的詞法環境對象裏面去;
1 LexicalEnviroment: { 2 a: undefined, 3 b: undefined, 4 test: 對函數的一個引用 5 } 6 7 //用聲明的方式創建的函數 8 function test(params) { 9 10 } 11 //用函數表達式創建的函數 12 var test1 = function(params) { 13 14 } 15 //用var定義的變量16 var a = 5; 17 var b; 18 //其他變量 19 c = 6;
定義一個聲明函數和一個函數表達式來證明這一點,代碼如下:
1 f(); 2 g(); 3 4 function f() { 5 console.log("ff"); 6 } 7 var g = function() { 8 console.log("gg"); 9 }
得到如下結果:
1 ff 2 e:\Code\JavaScript\day03\test2.js:2 3 g(); 4 ^ 5 6 TypeError: g is not a function
函數f被正常執行,而函數g報錯了
因為在預處理階段,函數f的引用被放在LexicalEnviroment對象中了,而g沒有,所以在調用時函數g()並不存在,所以報錯。
改一下位置,這樣就對了
1 f(); 2 var g = function() { 3 console.log("gg"); 4 } 5 g(); 6 7 function f() { 8 console.log("ff"); 9 }
這點在var定義變量上的體現:
1 console.log(a); 2 console.log(b); 3 4 var a = 5; 5 b = 6;
這段代碼的執行結果如下:
1 undefined 2 e:\Code\JavaScript\day03\test3.js:2 3 console.log(b); 4 ^ 5 6 ReferenceError: b is not defined
可見,如上所說,以var方式定義的a被添加到全局LexicalEnviroment{ }(詞法環境)對象中了,其值為undefined,而直接定義的b此時不存在,所以報錯。
這就是全局預處理階段的過程。
聲明:
關於全局的詞法環境對象LexicalEnviroment,在瀏覽器中就約等於window對象,該對象是屬於JS解析器的東西,在不同的地方叫法不同,比如在Node中稱為Execute Context(運行上下文對象)或許更合適一點,在ECMA -262標準中有其解釋,但我們無需關心其具體含義,只是有這個概念便可。
JS的解析與執行過程—(全局預處理階段)