對於你的第一個程式碼,如果你說你仔細看看它到底報的是什麼錯,你會發現,錯誤是這樣的:Uncaught TypeError: e is not a function。 這個錯誤表示,e不是函數,換句話說,就是e這個變數是存在的,但它不是函數。結合我們上面提到的三條規則,很容易就能想到,實際上它運行的是這個:
console.log(e());//error
if(true){
var e = function() {
return 10;
}
}
經過變數提升之後,會變成這樣:
var e;
console.log(e());
if(true){
e = function() {
return 10;
}
}
這其實是個歷史遺留問題…
以前在ES5的時候,規範規定函數只能在頂層作用域和函數作用域之中聲明,不能在區塊級作用域聲明。所以,類似這樣的語句其實都是非法的:
但是實際上各大瀏覽器出於相容性的考慮,都沒有遵守這個規範。
到了現在ES6的年代,規範規定了塊級作用域的存在,函數就可以在塊級作用域中定義了。
但其實事情並沒有這麼簡單,因為這樣的話,函數的定義行為就和以前不相容了,為了保證和以前的兼容性,ES6在附錄B裡面規定,瀏覽器的實現可以不遵守上面的規定,有自己的行為方式。
在ES6的瀏覽器中,它們的行為其實是這樣的:
允許區塊級作用域中定義函數
函數宣告實際上將會類似於使用
var
宣告的函數表達式,函數名稱將會提升至目前函數作用域頂同時函數宣告也會維持在區塊級作用域中的提升行為
對於你的第一個程式碼,如果你說你仔細看看它到底報的是什麼錯,你會發現,錯誤是這樣的:
Uncaught TypeError: e is not a function
。這個錯誤表示,
e
不是函數,換句話說,就是e
這個變數是存在的,但它不是函數。結合我們上面提到的三條規則,很容易就能想到,實際上它運行的是這個:經過變數提升之後,會變成這樣:
第二段程式碼就不必說了吧。
if 語句內函數申明不會被提升,和函數表達式一樣,所以第一個是語法錯誤,第二個會輸出10
相當於 =>