
當我們執行 doSomthing 的 function 的時候,會發現一開始 mom 是 undefined,繼續執行以後 mom 才會 被賦值成字串的 '老媽'。

如果我們執行下面的code,會發生甚麼事情呢?
console.log(name);
var name = '小美';
答案是

但如果今天是這樣的話
console.log(name2);
// var name2 = '小美';
執行結果


首先我們在執行環境之前,還有一個 創造環境 會先被執行。

可以從這張圖看到,我們在創造環境的時候,會是先把變數名稱放到記憶體中,而記憶體就像是物件的感覺,一個 keyname 對應一個 value 值。

接著就到 執行 的步驟,這時候才會把 值 賦予到記憶體對應的 value 的空間。


比較不同的是,當使用 函式陳述式 的時候,會在 創造環境 階段,直接把 keyname 以及 value 都放在記憶體中。

如果由這個例子來看,在創造環境的時,function 的 keyname 以及 value 都已經存在於記憶體中,到執行環境的時候,變數 a 才被賦值。

    var a = '1';
    console.log(a);
所以這段程式碼可以拆解成這樣
    // 創造階段
    var a;
    // 執行階段
    a = '1';
    console.log(a);
再來我們看另一段code
    function call () {
        console.log('呼叫');
    }
    call();
這樣的結果很明顯會顯示 '呼叫' 沒問題。
那麼改成這樣呢
    call();
    
    function call () {
        console.log('呼叫');
    }
還是一樣會顯示 '呼叫',因為在 執行階段 已經將 function 記錄在記憶體中,而執行階段才會執行 call(); 的程式碼。
所以 函式陳述式 不管放在哪裡都沒關係。
那如果是下面的程式碼呢?
    call();
    
    var call = function () {
        console.log('呼叫');
    }
執行結果會是:

透過這樣的方式(函式表達式)宣言function的話,就會跟變數的過程一樣:
    // 創造階段
    var call;
    // 執行階段
    call();
    call = function () {
        console.log('呼叫');
    }
那再來看到下面的例子,最後印出來的結果會是甚麼呢?
    function call () {
        console.log('call 1');
    }
    var call = function () {
        console.log('call 2');
    };
    call();
答案會是 call 2
因為雖然在 創造環境 的時候, call 的記憶體位置是裝著 console.log('call 1'); 。
但在 執行步驟 的時候, call 的記憶體位置被替換成 console.log('call 2'); 。
所以最後的執行結果是 call 2。
就算替換兩段 function 的位置,結果還是會一樣。
    var call = function () {
        console.log('call 2');
    };
    function call () {
        console.log('call 1');
    }
    call();
最後再來看一個練習題:
    call();
    
    function call () {
        if (dog) {
            dog = 'shiba';
        }
    }
    
    var dog = 'husky';
    console.log(dog);
這樣的執行結果,答案會是甚麼呢?
// husky
讓我們拆解流程來看看
    // 創造階段
    function call () {
        if (dog) {
            dog = 'shiba';
        }
    }
    var dog;
    // 執行階段
    call();
    
    dog = 'husky';
    console.log(dog);
雖然 function 中的判斷式有執行,但是這時候變數 dog 是 undefined ,判斷是會認為是 false,而不會進 dog = 'shiba'; 的賦值的動作。
最後來到 dog = 'husky';, 所以console.log 出來的就是 husky。
總結:函式陳述式在創造期間就已經“載入”,變數在執行期間賦值。
透過這些實例說明,希望可以讓大家更了解 hoisting 的概念。 汪汪
總結:函式陳述式在創造期間就已經“載入”,變數在執行期間賦值。
不能讓作者白白coding,感謝分享 (。・∀・)ノ゙
感謝~我已經補上總結了