[JavaScript - Udemy] Hoisting(創造與提升)

之前在Udemy的平台上趁特價買了JavaScript全攻略:克服JS的奇怪部分的中文課程,似乎是直接翻譯JavaScript: Understanding the Weird Parts的英文課程,在英文課程裡使用者回饋的評價算是很不錯的。

Hoisting(創造與提升)

這個階段是Javascript在初始化的時候會執行的動作。
當Javascript在一行一行執行程式碼以前,會先空出記憶體把所有變數和函示創造出來,但是先沒有放值進去。

我們直接看看範例(console.log後有斜線註解的地方代表有執行成功並寫出結果):

var a = 'Hi!';
function b () {
    console.log('Is b!'); //"Is b!"

}
console.log(a); //"Hi!"

b();

到這邊不難理解Js從第一行執行到最後一行會發生什麼事情以及他的特性,那如果把程式碼換個位置呢?

console.log(a); //undefined

b();
var a = 'Hi!';
function b () {
    console.log('Is b!'); //"Is b!"

}

第一行的console.log(a)並不是print出"Hi!"而是undefined,這是因為Javascript在初始化只會先空出記憶體去創造變數和函示,直到執行到給予該變數(例如:var a = 'Hi!';)。

以我們人類的看得懂的程式碼角度來看,Javascript在Hoisting的階段做了下列事情:

var a;
function b () {
    console.log('Is b!');
}

但如果我們沒有先創造創造變數的話Javascript就會報錯囉!
例如改變剛剛的例子把var a = 'Hi!';這行拿掉:

console.log(a);
//錯誤:Uncaught ReferenceError: a is not defined

b();
function b () {
    console.log('Is b!');
}

執行環境

再來要順便淺談一下執行環境問題,Javascript的Hoisting是在該環境唷!譬如剛剛的程式碼是在全域環境,此時Hoisting在全域環境的有本來就有的windowthis之外有自己創的變數a函示b,如果創造的變數不是在全域環境而是在函示裡面呢?(順帶一提現在開始是我個人推測、測試與驗證XD)

console.log(a); //undefined

b();
console.log(c);
//錯誤:Uncaught ReferenceError: a is not defined

var a = 'Hi!';
function b () {
    var c = 'Yo!';
    console.log('Is b!'); //"Is b!"

}

此時在執行console.log(c);時又報錯了因為全域與函示是不同的環境,所以在Hoisting的時候找不到變數c可以創造,所以程式碼再改寫一下:

b(); //"Is b!"

function b () {
    console.log(c); //undefined

    var c = 'Yo!';
    console.log(c); //"Yo!"

    console.log('Is b!'); //"Is b!"

}

我們發現函示裡面Hoisting運行的方式跟全域的方式是一樣的,那我們來做個執行順序的統整吧!

console.log(a); //undefined

b();
var a = 'Hi!';
console.log(a); //"Hi!"

function b () {
    var c = 'Yo!';
    console.log(c); //"Yo!"

    console.log('Is b!'); //"Is b!"

}

Hoisting沒問題之後再依造Javascript一行一行執行程式碼的特性,我們得出在console裡print出的順序為:undefined > "Yo!" > "Is b!" > "Hi!"

執行環境的地方是個人測試與淺見,如有觀念錯誤或更好的解釋方法歡迎留言糾正一下囉!

comments powered by Disqus