網頁

2019/2/3

JavaScript Hoisting

本篇簡單說明JavaScript Hoisting效果。


Hoisting是JavaScript的一種特性,變數宣告或函式宣告(function declaration)時,在編譯時即會先存入記憶體空間,直到被需要時才拿出來用,而不是執行時才存入記憶體空間,因此當執行到有hoisting效果的變數或函式時,不會有undefined的情況。

注意,以往有些解釋是說hoisting是將宣告提到程式的最上面,但這是錯誤的解釋,實際上程式碼的位置並沒有被移動。

一般我們可能以為程式由上往下執行,所以變數的宣告應該在使用之前如下:

var a; // 宣告變數a
a = "angry bird"; // 賦值給變數a
console.log(a); // angry bird

但因為hoisting的特性,以下印出的結果同上。

a = "angry bird";
console.log(a); // angry bird

var a; // 宣告變數a的在後,但因為hoisting所以已存在記憶體空間。

但若改成以下,則印出undefine,因為賦值並不會有hosting效果,只有變數的宣告才會。

console.log(a); // undefined
a = "angry bird";
var a;
var a;
console.log(a); // undefined
a = "angry bird";

下面一樣沒有hoisting的效果,hoisting效果僅限於變數的宣告,但變數的初始化(initialization)並沒有hoisting的效果。

console.log(a); // undefined

var a = "angry bird";

函式宣告(function declaration(function statement))同樣也有hoisting效果。

console.log(greeting()); // hello

// function declaration
function greeting() {
    return "hello";
}

function expression的函式宣告並沒有hoisting。

console.log(greeting()); // Uncaught TypeError: greeting is not a function

// function expression
var greeting = function() {
    return "hello";
}

儘管有此特性,實務上撰寫程式時最好還是避免在變數宣告前使用該變數來增加可讀性及維護性。

然而函式宣告卻需要hositing的特性,因為函式有時會互相呼叫(相互遞迴(mutual recursion)),在這種情況下若少了hoisitng特性,一定要先宣告才能使用,會造成一個函式無法呼叫另一個函式的情況。

function howDoYouDo(n) {
    console.log(n);
    if (n < 5) {
        console.log("How do you do.")
        response(++n);
    }
}
function response(n) {
    console.log(n);
    console.log(howDoYouDo(n))
}

howDoYouDo(1);

若要對hoisting有更深刻的了解,請參考我知道你懂 hoisting,可是你了解到多深?


沒有留言:

張貼留言