javascript和其他的語言有很多的不同之處,先行編譯就是其中之一,深挖進去會發現有很多的驚喜,同時也會讓你明白其中讓你迷惑的地方。
javascript代碼是分段執行的,以 script為邊界。在執行javascript程式碼片段之前會對代碼進行先行編譯。在先行編譯的過程中,引擎會對範圍內的變數進行聲明,並且初始化為undefined,解析定義式函數【注意和匿名函數的區別】。
直接上例題
例1
- mm=2;
- alert(mm); 彈出2
- var mm=2;
- alert(mm); 彈出2
這裡大家都明白,不再多說
例2
- alert(mm);
- mm=2; 錯誤提示,mm未定義
我的個人理解是引擎在全域中對代碼先行編譯的階段,把沒有用var聲明的全域變數解釋為向上一級對象的屬性,這裡我稱之為虛對象,所以會出現未定義的提示
例3
- alert(mm);
- var mm=2; 彈出undefined
引擎在對程式碼片段先行編譯時,把變數定義為undefined;alert執行的時候,mm還沒有進行賦值,所以會彈出undefined
下面這段代碼跟上面原理一樣
- var mm=2;
- (function test()
- {
- alert(mm);
- var mm=3;
- })() 彈出undefined
例4
聲明一個定義式的函數【不是匿名函數】
- test()
- function test()
- {
- var mm=2;
- alert(mm);
- } 彈出2
引擎對定義式的函數會進行解析,在test執行前,test這個函數已經解析完畢,所以會彈出2
例5
- test()
- var test=function ()
- {
- var mm=3;
- alert(mm);
- } 出現提示 缺少對象
因為此時匿名函數被賦予給一個變數,而引擎在對變數解析的時候會把變數定義為undefined;另一方面,函數也是對象,test執行的時候,test函數未被解析,所以會出現錯誤提示 缺少對象
總結:javascript中的代碼是分段執行,引擎會對代碼進行先行編譯,把範圍中的變數定義為undefined,解析定義式的函數,匿名函數不會解析,原因不再多說。