筆者在這裡附上一段代碼,請讀者思考一下程式的運行結果: 運行結果如下: 不知道讀者有沒有猜對呢?哈哈,可能很多讀者會認為第一行的console.log(a);會輸出undefine ,因為大家都知道變數提升與函數提升,而Javascript編譯器執行代碼也是逐行執 行,當js文件首先載入到記憶體時,編 ...
筆者在這裡附上一段代碼,請讀者思考一下程式的運行結果:
console.log(a); //??? a(); var a=3; function a(){ console.log(10); } console.log(a);//??? a=6;
運行結果如下:
console.log(a); //輸出function a(){} a(); var a=3; function a(){ console.log(10); } console.log(a);//3 a=6;
不知道讀者有沒有猜對呢?哈哈,可能很多讀者會認為第一行的console.log(a);會輸出undefine ,因為大家都知道變數提升與函數提升,而Javascript編譯器執行代碼也是逐行執
行,當js文件首先載入到記憶體時,編譯器便會對代碼執行預編譯,將代碼中的var 聲明與function聲明提升到頭部,再一行行的去執行代碼,那這樣的邏輯的話,可能讀者會想,既然
變數提升,上面的代碼在預編譯期間應該首先會提升var a,再提升function a(){}, 等執行console.log(a)的時候,自然輸出undefine,沒有被定義才對啊。
這裡向讀者強調一下一個容易被忽視的小問題。,雖然JS預編譯期間會對var 和 函數聲明提升,但是函數聲明提升是優先於變數提升的(也適用於函數字面量聲明的情況,這
里不做演示),所以應該是先提升function a(){}.再提升var a,所以第一行輸出了function a(){},有沒有一種恍然大悟呢?哈哈。
而console.log(a);這一行為什麼輸出3而不是6或者function a(){} 呢,我們再回憶一下JS已經將function a(){} 與var a 提升到了頭部,首先分析末尾的代碼a=6;這行代碼編譯器
並沒有執行到這一行,所以忽略,現在就是糾結到底是3還是function a(){},,而輸出結果卻告訴我們是3,至於已經聲明過的function a(){},去哪裡了呢。
這裡為讀者解析一下程式的運行狀態,在我們預編譯階段function a(){}和var a已經存在於記憶體中,只是這時var a並沒有被賦值,而接下來執行了a(),這裡我們要強調一下,
每種語言都有垃圾回收機制,程式中已經用過的函數,當他執行完畢後,便會被當做垃圾回收掉,而a()執行完後 ,便會被回收,而記憶體裡面只剩下了var a; 接下來再執行下一
句var a=3;所以末尾的console.log(a);便輸出了3 而不是function a(){}。
總結:第一、JS預編譯階段函數聲明提升優先於變數提升,第二、當函數被使用後,便會被垃圾回收。