搜尋

首頁  >  問答  >  主體

javascript - if語句 對函數宣告影響

console.log(e());//error

if(true){
    function e() {
        return 10;
    }
}
if(true){

    function e() {
        return 10;
    }
}
console.log(e());//10

如果函數宣告提升只提升到了if作用域內,那麼以上又是什麼原因呢? (chrome58測驗) 為何外部又能存取if的作用域內的函數? 求大神解

滿天的星座滿天的星座2720 天前705

全部回覆(3)我來回復

  • 伊谢尔伦

    伊谢尔伦2017-06-12 09:29:40

    這其實是個歷史遺留問題…

    以前在ES5的時候,規範規定函數只能在頂層作用域和函數作用域之中聲明,不能在區塊級作用域聲明。所以,類似這樣的語句其實都是非法的:

    if (true) {
        function f() {}
    }

    但是實際上各大瀏覽器出於相容性的考慮,都沒有遵守這個規範。

    到了現在ES6的年代,規範規定了塊級作用域的存在,函數就可以在塊級作用域中定義了。
    但其實事情並沒有這麼簡單,因為這樣的話,函數的定義行為就和以前不相容了,為了保證和以前的兼容性,ES6在附錄B裡面規定,瀏覽器的實現可以不遵守上面的規定,有自己的行為方式。


    在ES6的瀏覽器中,它們的行為其實是這樣的:

    1. 允許區塊級作用域中定義函數

    2. 函數宣告實際上將會類似於使用var宣告的函數表達式,函數名稱將會提升至目前函數作用域頂

    3. 同時函數宣告也會維持在區塊級作用域中的提升行為

    對於你的第一個程式碼,如果你說你仔細看看它到底報的是什麼錯,你會發現,錯誤是這樣的: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;
        }
    }

    第二段程式碼就不必說了吧。

    回覆
    0
  • 滿天的星座

    滿天的星座2017-06-12 09:29:40

    if 語句內函數申明不會被提升,和函數表達式一樣,所以第一個是語法錯誤,第二個會輸出10

    回覆
    0
  • 欧阳克

    欧阳克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

    回覆
    0
  • 取消回覆