Jeff的隨手筆記

學習當一個前端工程師

0%

『JavaScript 基礎』Execution context

Imgur

這是一門在Udemy 課程,是同學介紹的。主要是因為想要運用到過年前這段時間好好的增進自己的JavaScript的基礎能力,讓自己能往前端工程師更近一步。主要還是會以筆記的形式做呈現!


上一篇我們有提到 Execution context,這篇我們來深度解析

先來看一對程式碼:

1
2
3
4
5
6
7
b();
console.log(a);

var a = "Hello World"
function b() {
console.log('Called b !')
}

我們得到的結果是:

1
2
Called b!
undefined

為什麼印出來的會是undefined 而不是 error呢?

我們在試一個把宣告拿掉

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

// var a = 'Hello World!';

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

我們得到的是:

1
2
Called b!
ReferenceError: a is not defined

為什麼?????

第一次我以為會出現error結果沒有,第二次我以為會跟第一次一樣結果出現error。

這個現象是一個叫做 『hoisting』的概念。

要了解JavaScript 之所以可以這麼做,我們要了解Execution context的創建方式:

其實Execution context 是分兩個階段創建的。變數跟函式在某總程度上是可以用,即便他們是寫在console 後面,就是因為這個原因。下面我們看看是分哪兩個階段:

第一階段是創造(creation)

在這個階段,JavaScript引擎會在儲存空間中確認要創建變數以及函式的位子,然後創建出來,但是還沒把值放到變數中,所以當程式碼開始執行時,我們才可以使用它們。

第二階段就是執行(execution)

執行時函式跟變數就有些不同了,在JavaScript裡,所有的變數在最初的設置都是undefined,而函式在最初設置就是完整的。

所以,我們可以這樣解讀:
JavaScript引擎在執行我們的程式碼,是先依照程式碼上我們宣告的變數跟函式在記憶體中創建他們的位子,然後才會開始一行一行執行下來,因為變數在最初的設置都是undefined,所以在執行到console.log(a)時,因為還沒有執行到 var a = “Hello World” 所以印出來的會是undefined。

PJ助教在自己的部落格有補充到:在我們定義變項的過程中,可以分成宣告(declaration)和給值(initialization)的兩個過程,只有declaration的內容會在逐行執行程式前先被執行並儲存在記憶體中(hoisted);給值的內容則是在hoisted後,逐行執行程式時,才會被執行到。


補充:

undefined 與 not defined

在剛剛的案例中,我們有看到兩個詞:undefined 跟 not defined。

undefined 跟 not defined 差在哪邊?

剛剛在說hoisting 時有提到,JavaScript 引擎會先在記憶體創建屬於變數的空間,並且在未賦值前都會是undefined。

在JavaScript中 undefined 是一個特殊關鍵值,代表尚未被定義。not defined 則是代表我們在儲存空間中沒有找到這個。

因此我們可以說 undefined是尚未給定義但已宣告變項的值,但是not defined則是該變項尚未宣告過,執行後會出現錯誤訊息!

參考資料:

談談Javascript 中的 Hoisting