js變量提高與函數提高的機制

問題

clipboard.png

在這個例子中它應該輸出什麼?輸出的結果是6。閉包

clipboard.png

這個例子中它又該輸出什麼?輸出的結果是a(),也就是輸出了函數指針a。函數

這雖然是個變量和函數提高的問題,可是這二者究竟是怎麼提高的?spa

js是怎麼建立變量的

var a=1;
var b=2;

這是否是聲明瞭變量就立馬接着給聲明的變量賦值了?指針

js解析這個代碼時,它其實是按照以下方式解析的code

var a;
var b;
a=1;
b=2;

也就是js會先把全部變量都聲明好了以後,而後才進行賦值,並非聲明一個變量就賦值,再聲明一個再賦值。js所謂變量提高,提高就是爲了事先聲明變量。ip

clipboard.png

上圖中左邊的例子,js解析時候是按照按照右邊的代碼解析的。js會把全部變量都集中提高到做用域頂部事先聲明好,可是它賦值就就並非像變量聲明那樣集中着一個個挨着賦值。本來書寫賦值時寫在哪裏,那麼js解析運行到那一行以後纔會進行賦值,尚未運行到的就不會事先賦值。也就是變量會事先聲明,可是變量不會事先賦值。作用域

函數和變量都提高時,誰提到前面誰提到後面

在做用域中,無論變量和函數寫在什麼位置,全部變量會被總體提高到做用域頂部,全部函數也會被總體提高到做用域頂部,可是函數總體在變量總體的後面。it

clipboard.png

從這個例子中能夠看到,變量和函數都總體提高後,函數總體在變量的後面。變量提高以後,但其賦值仍是留在本來的位置等js運行到了以後動態賦值,而函數提高以後直接至關於在代碼裏抽空了。class

clipboard.png

在這個更復雜一點的例子中,變量和函數提高後,js實際上就把它轉變爲了右邊的代碼在運行。變量

搞明白這個例子也就搞懂了做用域中變量和函數是怎麼提高的。

結語

回到開頭的兩個問題

clipboard.png

它們各自被js轉換後如上

clipboard.png

一個思考題,這個例子該輸出什麼?

「提高」的本質就是爲了事先聲明變量和函數,固然函數只有聲明式函數纔會被提高,字面量函數不會被提高。這種提高就是存在於做用域中,包括全局做用域、函數做用域(閉包造成的做用域也是個函數做用域),總之都是在做用域中聲明變量和函數時,會提高到做用域頂部,進行事先聲明。

相關文章
相關標籤/搜索