昨天個人一個技術交流羣裏發了一段代碼,涉及的是變量和函數的聲明提高,執行結果很是讓人迷惑,你們討論許久,仍是有地方解釋不清楚,到最後,仍是發佈到stack overflow
,經過大佬解惑才弄明白,這裏我再整理一下。javascript
逐個解析一下討論到的案例:html
沒有特別說明的,運行環境就是是chrome77。
var a if(true) { a = 5 function a() {} a = 0 console.log(a) } console.log(a)
先整理一下個人思路:java
變量a
聲明;if語句塊
,是一個塊級做用域;變量a
的賦值,還聲明瞭一個函數a
。按照聲明提高原則,函數a
聲明會被提高,這裏沒有使用let
、const
,因此我按ES5
以前的聲明提高規則去分析的。es6
沒有塊級做用域,提高到全局,並且函數聲明優先於變量聲明,因此會覆蓋變量a的聲明。web
那麼答案是:chrome
0 0
很遺憾,這個答案是錯的,至少現代瀏覽器是錯的(我後來在IE的模擬環境運行,確實是這個結果)。瀏覽器
如今,公佈一下正確答案:函數
0 5
這個答案很是讓人疑惑不解:code
第二個輸出5,究竟是怎麼回事?htm
let a = function(){}
,那麼a=5
是暫時性死區;var a = function(){}
,那麼會和上面同樣,輸出0 0
;先看看代碼運行解析[引用1],咱們能夠把代碼運行當作這樣:
var a¹; if (true) { function a²() {} // hoisted a² = 5; a¹ = a²; // at the location of the declaration, the variable leaves the block a² = 0; console.log(a²) } console.log(a¹);
解釋一下:
變量a
聲明,這裏沒有問題。函數a
聲明提高,提高到塊級域頂部。a=5
,這裏賦值的對象是本地的函數a
,覆蓋了。函數a
聲明處,本地的變量a
覆蓋了全局的變量a
。按照[引用2]解釋,這裏也是提高,也就是說函數a
聲明提高了兩次。到這裏疑惑終於解開了!這裏要說明兩點:
ES5
中是非法的,在ES6
中並無嚴格規定(考慮到向下兼容性,參考阮老師的ES6入門),也就是這塊依賴於實現[引用3]。](https://stackoverflow.com/que...