在 JavaScript 中,提升(Hoisting)可能是最奇怪的部份了,這個部份還滿容易搞混的,不過希望我整理出來的筆記能夠幫助釐清觀念,如果有錯的部分麻煩請告知我。

首先看一段程式碼,然後看會發生什麼事:

1
2
3
4
5
6
7
8
var a = 'Hello World';

function b() {
console.log('Test');
}

console.log(a);
b()

上面的程式碼沒有意外的出現 Hello WorldTest
如果把第 8 跟第 9 行移到最上面的話,會發生什麼事呢?

1
2
3
4
5
6
7
8
console.log(a); // undefined
b(); // "Test"

var a = 'Hello World';

function b() {
console.log('Test');
}

結果沒有出現錯誤,而是得到一個值 undefined,另一個函式則是成功執行。
這在其他大部分程式語言是沒有辦法執行的,但是在 JavaScript 卻可以執行(至少我在 Ruby 試過不行),
而這個現象叫做提升 (Hoisting)。

這個現象並不是說真的把你的程式碼移到最上面,而是在一行一行執行程式碼之前,JavaScript 會先做一次預編譯,為了變數和函式在記憶體中建立一個空間,所以當程式碼被逐行執行時,就可以馬上找到它們。

那麼為什麼變數跟函式得到的結果不同呢?

這是因為所有 JavaScript 的變數,在一開始都會被設定為 undefined,表示不知道它的值,就算不設值的話,也是一樣得到 undefined。

1
2
3
4
5
6
7
8
console.log(a); // undefined
b(); // "Test"

var a;

function b() {
console.log('Test');
}

而在程式碼在第一行發現 a 沒有值,就直接給 undefined。

函式不同的是,前面有說到,執行前會做一次預編譯,在這過程中,定義式函式會優先執行,會被完全設定好放在記憶體中,等到執行時發現這裏有一個函式,在記憶體已經有值了,於是可以馬上讀取。

雖然 JavaScript 有提升這個特性,但是還是建議要用到的變數,還是盡可能地在上面宣告再使用。