JavaScript 預編譯(變量提升和函數提升的原理)


本文部分內容轉自https://www.cnblogs.com/CBDoctor/p/3745246.html

1.變量提升

 1 console.log(global); // undefined
 2 var global = 'global';
 3 console.log(global); // global
 4  
 5 function fn () {
 6   console.log(a); // undefined
 7   var a = 'aaa';
 8   console.log(a); // aaa
 9 }
10 fn();

疑問一:

還沒有定義a和global,為什么就變成了undefined呢?

 

2.函數提升

1 console.log(f1); // function f1() {}   
2 console.log(f2); // undefined  
3 function f1() {}
4 var f2 = function() {}

疑問二:

console.log(f1)為什么能夠輸出還未定義初始化的f1函數呢?

疑問三:

類似於疑問一,為什么f2還沒定義,就輸出undefined呢?

 

這些疑問的答案,都來自JS的預編譯機制:

 

3.預編譯

JS並不會完全按照代碼順序進行解析執行,而是在解析之前進行一次“預編譯”。在此過程中,會把:

(1)定義式的函數優先執行

(2)所有var變量定義,默認值為undefined

這就解釋了上面兩段代碼輸出的原因了,上面的兩段代碼我們可以用下面的形式理解:

變量提升:

 1 var global;
 2 console.log(global); // undefined
 3 global = 'global';
 4 console.log(global); // global
 5  
 6 function fn () {
 7       var a;
 8   console.log(a); // undefined
 9   a = 'aaa';
10   console.log(a); // aaa
11 }
12 fn();

函數提升:

1 function f1() {}
2 var f2;
3 console.log(f1); 
4 console.log(f2); 
5 f2 = function() {}

 

4.容易出錯的一點

 1 // 調用函數,返回值1
 2 f();                                 
 3 function f(){
 4     alert(1);
 5 }
 6 
 7 // 調用函數,返回語法錯誤。
 8 f();                                 
 9 var f = function(){
10     alert(1);
11 }

這個一看就懂為啥了,在預編譯階段,聲明了變量f,而沒有為它賦值(匿名函數)。直接調用,肯定出錯。

 

5.總結

  JS加載包含預編譯和執行兩個階段。 編譯階段會對所有的var變量和function進行掃描,並將var變量初始化為undefined類型,而function則被初始化為函數值。

  到了執行階段,JS從上面往下面依順序執行,遇到var變量便進行賦值(因此,在賦值之前進行調用的話會出現錯誤).遇到函數變量的話會從活動對象中尋找函數


免責聲明!

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



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