當我們執行 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,感謝分享 (。・∀・)ノ゙
感謝~我已經補上總結了