--- tags: Javascript --- # Javascript 提升(Hoisting) ## 介紹 提升(Hoisting)是在 [ECMAScript® 2015 Language Specification](https://www.ecma-international.org/ecma-262/6.0/index.html) 裡面找不到的專有名詞。它是一種釐清 JaveScript 在執行階段內文如何運行的思路(尤其是在創建和執行階段)。然而,提升一詞可能會引起誤解:例如,提升看起來是單純地將變數和函式宣告,移動到程式的區塊頂端,然而並非如此。變數和函數的宣告會在編譯階段就被放入記憶體,但實際位置和程式碼中完全一樣。 by. MDN ## 創造環境與執行 在創造環境的時候會先將a變數寫入記憶體,執行環境才將1賦予給a。 ![](https://i.imgur.com/f4VbIR1.jpg) ## 函式陳述式創造階段 而函式陳述式在創造環境就被寫入,在執行任何程式碼前,JavaScript 會把函式宣告放進記憶體裡面,這樣做的優點是:可以在程式碼宣告該函式之前使用它。 ![](https://i.imgur.com/xHSMtNn.jpg) ## 範例 ### 範例1 函式與變數範例 ```javascript= // undefined console.log(a); var a = 1; // 以下輸出 你好 function hello() { console.log("你好"); } hello(); ``` 將以上程式碼拆解,就可以看到a是在執行階段才被賦予值,而函式陳述式在創造階段就被創造所以可以輸出"你好" ```javascript= // 創造階段 var a; // 執行階段 console.log(a); a = 1; // 創造階段 function hello() { console.log("你好"); } // 執行階段 hello(); ``` ### 範例2 函式範例 ```javascript= var hello = function () { console.log("函式表達式"); }; function hello() { console.log("函式陳述式"); } hello(); // 函式表達式 ``` 他會輸出 '函式表達式' 因為**創造階段函式優先**,將以上分解 ```javascript= // 創造階段 var hello; function hello() { console.log("函式陳述式"); } // 執行 hello = function () { console.log("函式表達式"); }; hello(); // 函式表達式 ``` ### 範例3 再看看這個範例 ```javascript= // 以下輸出 undefined hello(); function hello() { console.log(text); } var text = "Hello World"; ``` 將範例依照上面所說邏輯拆解,就可以看到在函式呼叫時,還未將text賦予Hello World,所以會輸出undefined ```javascript= // 創造階段 function hello() { console.log(text); } var text; // 執行 hello(); // undefined text = "Hello World"; ``` ### 範例4 看到可能會想說怎麼不是先輸出'我是第一個函式'再輸出'我是第二個函式' ```javascript= function hello() { console.log("我是第一個函式"); } hello(); // 我是第二個函式 function hello() { console.log("我是第二個函式"); } hello(); // 我是第二個函式 ``` 來將上述範例分解,可以看到輸出'我是第一個函式'的函式被覆蓋掉了,所以都會輸出相同內容 ```javascript= // 創造階段 function hello() { console.log("我是第一個函式"); } function hello() { console.log("我是第二個函式"); } // 執行 hello(); hello(); ```