console.log(e());//error
if(true){
function e() {
return 10;
}
}
if(true){
function e() {
return 10;
}
}
console.log(e());//10
如果函數宣告提升只提升到了if作用域內,那麼以上又是什麼原因呢? (chrome58測驗) 為何外部又能存取if的作用域內的函數? 求大神解
伊谢尔伦2017-06-12 09:29:40
這其實是個歷史遺留問題…
以前在ES5的時候,規範規定函數只能在頂層作用域和函數作用域之中聲明,不能在區塊級作用域聲明。所以,類似這樣的語句其實都是非法的:
if (true) {
function f() {}
}
但是實際上各大瀏覽器出於相容性的考慮,都沒有遵守這個規範。
到了現在ES6的年代,規範規定了塊級作用域的存在,函數就可以在塊級作用域中定義了。
但其實事情並沒有這麼簡單,因為這樣的話,函數的定義行為就和以前不相容了,為了保證和以前的兼容性,ES6在附錄B裡面規定,瀏覽器的實現可以不遵守上面的規定,有自己的行為方式。
在ES6的瀏覽器中,它們的行為其實是這樣的:
允許區塊級作用域中定義函數
函數宣告實際上將會類似於使用var
宣告的函數表達式,函數名稱將會提升至目前函數作用域頂
同時函數宣告也會維持在區塊級作用域中的提升行為
對於你的第一個程式碼,如果你說你仔細看看它到底報的是什麼錯,你會發現,錯誤是這樣的: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;
}
}
第二段程式碼就不必說了吧。
欧阳克2017-06-12 09:29:40
if(true){
function e() {
return 10;
}
}
相當於 =>
var e
//e为undefined 所以下面报错
console.log(e());//error
if(true) {
e = function() {
return 10;
}
//if内的其他语句
}
//e已经被修改为function了,所以下面的语句正常
console.log(e());//10