[JS] Hoisting 提升
hoisting 提升
hoisting 提升的作用使變數和函數的宣告看起來移動到程式碼的頂端,但實際上並非如此,而是程式在編譯期間在宣告變數和函數的部分會先建立記憶體空間,在執行的時候才會將值賦予到該記憶體空間。
看後面的程式來了解更多 hoisting 的特性。
變數的 hoisting
對未宣告的變數存取時拋出
not defined
的錯誤1
console.log(a); // Uncaught ReferenceError: a is not defined
hoisting 的作用使宣告的變數值為
undefined
1
2console.log(a); // undefined
var a = 10;
可以將以上程式想像成以下(之所以為想像是因為原理並不是真的 JavaScript 引擎會將程式碼變換成如下)
1 | var a; |
第 1, 2 行由於宣告但還未賦予值,所以為 undefined
,由此可以看出將 var a = 10
拆解成 var a
及 a = 10
兩部分,只有 var a
宣告的部分會有 hoisting 的效果,賦值則不會。
函式的 hoisting
上面的例子為變數的 hoisting,但 function 也有 hoisting,關於 function 的部分又可分為 var a = function() {...}
及 function a() {...}
兩種來看。
- 函式運算式
var a = function() {...}
相當於以下1
2
3
4
5x(); // Uncaught TypeError: a is not a function
var x = function() {
console.log('test');
};可以看到只有1
2
3
4
5
6var x;
x(); // Uncaught TypeError: a is not a function
x = function() {
console.log('test');
};var x
宣告變數的部分提升,後面指定 function 的部分則不會提升。
所以函式運算式不會提升。
- 函式宣告
function a() {...}
從結果可以看出來宣告函式會連同內容一起提升,所以在程式碼中可以在宣告之前使用函式。1
2
3
4
5x(); // test
function x() {
console.log('test');
}
所以函式宣告會提升。
函式及變數同名的 hoisting
雖然實務上不會將變數及函式命名一樣的名稱…,但這部分也有規律所在就來了解一下。
函式與變數同名,函式會優先於變數
1
2
3
4
5
6
7console.log(x); // ƒ x() {...}
var x;
function x() {
console.log('test');
}從結果不是
undefined
可以看出即使變數和函數都提升,函式會優先變數。
多個變數同名
這裡要說的多個變數同名情況很多人以為最後宣告沒有賦予值所以 x 會是undefined
,但結果卻是 51
2
3
4var x = 5;
var x;
console.log(x); // 5以上代碼相當於以下,仍然是基礎的 hoisting 特性
1
2
3
4
5var x;
var x;
x = 5;
console.log(x); // 5
多個函式同名,最後宣告的會覆寫前面的宣告
1
2
3
4
5
6
7
8
9
10
11
12
13x(); // 3
function x() {
console.log(1);
}
function x() {
console.log(2);
}
function x() {
console.log(3);
}
參考資料