對Javascript到底了解多少,一測便知道
筆者在這裏附上一段代碼,請讀者思考一下程序的運行結果:
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預編譯階段函數聲明提升優先於變量提升,第二、當函數被使用後,便會被垃圾回收。
對Javascript到底了解多少,一測便知道