大部分只是整理筆記,歡迎隨意看看

0%

JS - Hoisting 的觀念

前言

本篇用來記錄自己所了解的 Hoisting 觀念

函式的 Hoisting

在執行程式的時候,JavaScript 會將所有宣告的函式先放入記憶體之中,所以即使撰寫的順序是先執行再宣告也不會出錯,
請看以下範例:

1
2
3
4
5
6
撰寫時的順序
call('媽媽'); // 打給媽媽

function call(name) {
console.log('打給' + name);
};

從上面這個範例就可以稍微了解 Hoisting 的觀念,雖然還沒宣告函式,但是還是可以正常執行,就是因為 JavaScript 先把宣告函式的部分提升到最上方,所以實際上執行順序應該像下面的範例:

1
2
3
4
5
6
實際執行時的順序
function call(name) {
console.log('打給' + name);
};

call('媽媽'); // 打給媽媽

變數的 Hoisting

實際上在執行程式的時候變數也會被提升,但是要注意的是雖然會被提升,但是卻不會先賦值,稍微看一下下面這個範例:

1
2
console.log(name); // undefined
var name = '名字';

這個範例實際執行後我們可以得到 undefined 這個結果,原因我們來看看下面的程式:

1
2
3
4
實際執行時的狀況
var name
console.log(name); // undefined
name = '名字';

雖然變數會被提升,但是以本範例來說只提升了 var name 的部分,所以才會在呼叫時出現 undefined。

補充

下面補充一些容易搞錯的陷阱。
下面的範例執行後會得到 1 的結果,而原因就是雖然變數會被提升但不會先被賦值,所以這時候 a 還是 undefined,這會導致函式跳過 if 的判斷,所以答案還是 1。

1
2
3
4
5
6
7
8
fn(); 
function fn()
  if (a) { 
    a = 2
  }; 
};
var a = 1
console.log(a); // 1

宣告的方式也會影響是否會被提升,我們來看看兩個例子:

1
2
3
4
範例一
function fn() {
  console.log('1');
};
1
2
3
4
範例二
var fn = function() {
  console.log('1');
};

範例一可以正常被提升,但是範例二只有 var fn 的部分會提升,而賦值的部分不會,所以範例二在最上面使用 fn() 的話會沒辦法執行。

下面這個問題會得到什麼樣的結果呢?

1
2
3
4
5
6
7
8
9
function foo() {
    console.log('1');
};
foo(); // 第一次執行
 
function foo() {
    console.log('2');
};
foo(); // 第二次執行

答案是會得到兩次 2,原因則是第二個函式會覆蓋掉第一個,而因為函式會被提升的關係,所以執行起來會像是下面的感覺:

1
2
3
4
5
6
7
8
9
function foo() {
    console.log('1');
};
function foo() {
    console.log('2');
};

foo(); // 第一次執行
foo(); // 第二次執行

參考

參考資料:
https://developer.mozilla.org/zh-TW/docs/Glossary/Hoisting
https://www.youtube.com/watch?v=s0qX9PgJlN4