iT邦幫忙

0

Javascript 進階 2-6 提升

  • 分享至 

  • xImage
  •  

我們先來看看下面這段code的執行結果

https://ithelp.ithome.com.tw/upload/images/20191007/20121770GvHsVuPNFD.png

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

https://ithelp.ithome.com.tw/upload/images/20191007/20121770VUvnkC2YT4.png

如果我們執行下面的code,會發生甚麼事情呢?

console.log(name);

var name = '小美';

答案是

https://ithelp.ithome.com.tw/upload/images/20191007/20121770VOUKbYyQ1u.png

但如果今天是這樣的話

console.log(name2);

// var name2 = '小美';

執行結果

https://ithelp.ithome.com.tw/upload/images/20191007/201217708lkHejSHoC.png

而這個就是我們今天要討論的主題 -- 提升

https://ithelp.ithome.com.tw/upload/images/20191007/20121770PZxNdhjxzA.png

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

https://ithelp.ithome.com.tw/upload/images/20191007/20121770LG7uKPnOD8.png

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

https://ithelp.ithome.com.tw/upload/images/20191007/20121770RJYZFuBoWk.png

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

https://ithelp.ithome.com.tw/upload/images/20191007/20121770TvZe3Y78Tk.png

https://ithelp.ithome.com.tw/upload/images/20191007/20121770DwMePuNaSo.png

在創造環境的時候,把記憶體空間準備好,這個流程我們就叫做 -- 提升

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

https://ithelp.ithome.com.tw/upload/images/20191007/20121770k9Mzwga2N2.png

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

https://ithelp.ithome.com.tw/upload/images/20191007/201217706c5AGaKlMt.png

    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('呼叫');

    }

執行結果會是:

https://ithelp.ithome.com.tw/upload/images/20191007/20121770cGjXhglBLP.png

透過這樣的方式(函式表達式)宣言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 的概念。 汪汪


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
lolis
iT邦新手 5 級 ‧ 2019-12-27 16:09:50

總結:函式陳述式在創造期間就已經“載入”,變數在執行期間賦值。

不能讓作者白白coding,感謝分享 (。・∀・)ノ゙

odinhusky iT邦新手 5 級 ‧ 2020-05-17 10:59:28 檢舉

感謝~我已經補上總結了

我要留言

立即登入留言