這篇博文是以前在CSDN寫的,如今移至sf。編程
有過C或者Java類編程經驗的同窗,對於「先聲明後使用」的規則很熟悉,若是使用未聲明的變量或者函數,編譯時程序會報錯!可是,JavaScript倒是一個‘大奇葩’,能夠在變量或者函數聲明以前使用,如今根據個人理解在作一下說明。微信
首先說明JS的hoist分爲變量hoist
和函數hoist
兩種。函數
看一段程序code
var a=10; function fun(){ console.log(a); var a=100; console.log(a); } fun();//undefined 100 console.log(a);//10
咱們知道在js中,做用域分爲全局做用域和函數做用域兩種(ES6新特性,增長了塊級做用域,另作說明)。全局變量聲明有三種方式:對象
好,很顯然,var a=10;在程序中是全局變量。那麼,按照咱們正常的邏輯輸出結果爲:10 100 10。可是,實際輸出結果爲:undefined 100 10,實際上是JS解析器的解析緣由,它會將當前做用域中聲明的全部變量和函數,放在做用域的最開始處。可是變量只有其聲明被提早在做用域的最開始處,賦值結果仍然還在原來位置。上述代碼對於解析器來講,實際上是:ip
var a=10; function fun(){ var a; console.log(a); a=100; console.log(a); } fun();//undefined 100 console.log(a);//10
講完變量hoist
,如今再講一下函數hoist
,函數hoist又分爲兩種狀況。一種是函數聲明
,另外一種是函數做爲值賦值給變量
。作用域
先說第一種狀況:io
fun();//2 function fun(){console.log(2);}
在這種狀況下,能夠看出,函數JS解釋器容許在函數聲明以前使用函數,其實也就說明,在這種狀況,不只函數名提早了,同時,函數體也被提早。因此能夠上述代碼能夠執行。再說第二種狀況:console
fun(); var fun=function(){ console.log(2); }
結果爲:Uncaught TypeError: fun is not a function
能夠看出在此例中,函數只是變量聲明聲明提早,可是賦值沒有提早,而且被提早的變量默認爲undefined
,因此報的錯誤類型爲「typeerror」,由於undefined不是函數,不能被調用。編譯
function fun(){console.log(1);} fun();//2 function fun(){console.log(2);} fun();//2 var fun=100; console.log(fun);//100 fun();//報錯
在此例中,函數名和變量名相同,都是fun,都會提早,那麼在提早時,有什麼須要注意的地方呢?
函數聲明比變量聲明更置頂
聲明過得變量不會重複聲明
因此上述代碼等效於:
function fun(){console.log(1);} function fun(){console.log(2);}//函數體覆蓋上一層函數體 var fun;//實際無效 fun(); fun(); fun=100; console.log(fun); fun();
以上就是本人對於JS的hoist問題的理解,若是哪位同窗,發現其中有誤,歡迎指正!個人微信號爲:Alfred-kai。