為了知道那些常被拿來考觀念的專有名詞是哪裡來的,
這篇要先整理 JS的 Execution Context!
『當JS引擎執行一段程式碼(script)時,便會創造 execution contexts。』
『且每個execution context 包含兩個階段:創造階段 creation phase 和 執行階段 execution phase。』
引用自JavaScript Tutorial Website的解釋:
When a JavaScript engine executes a script, it creates execution contexts. Each execution context has two phases: the creation phase and the execution phase.
(引用自 JavaScript Execution Context )
→ 也就是說,Execution contexts 包含了程式碼 創造物件 到 執行 的過程。
到這裡先記一個結論,接下來先繼續看實際上發生了什麼事。
所以Execution Context到底在做什麼?
在執行過程中,JS裡的物件會被初始化和給值。
假設現在JS要執行一個script,那麼他就會:
在剛剛提到的定義裡,可以發現定義裡的execution context"s"是複數形,
由此可知會產生的execution context其實不只有一個,而程式碼會執行的execution context分為兩種:
並且,它們各自包含了 創造階段 creation phase 和 執行階段 execution phase,
所以這邊先畫個簡表,我們現在有的資訊大概長這樣:
而我們學習目標,就是要知道這段過程,哪個物件先創造? 什麼時候被指派? 被指派給誰?
知道重點是什麼就可以往下看了~
當初次 執行一個script時,JS引擎會創造第一種 execution context,叫 Global Execution Context。
然後先進入 創造階段 creation phase :
window
object,或Node.js中的 global
object。)this
object,並被綁定至 global object。variables
和 function
分配至記憶體,並初始化為 undefined。講太多抽象的概念不好理解,讓我們假設一個求面積的程式碼範例:
let a = 3;
function area(s){
return s * s;
}
let b = area(a);
console.log(b);
在這個階段,各object會被初始化,也就是程式碼會知道有這個object存在,但變數還不會被賦值。
因此 Global Execution Context在 creation phase 的狀態如下:
object | value | 備註 |
---|---|---|
global object | window | 因為在瀏覽器里執行,因此global object 為 window |
this | window | 這時的this也指向 window object |
a | undefined | |
area | function(){...} | |
b | undefined |
接著,Global Execution Context 會來到 執行階段 execution phase:
這時JS的script便會逐行被執行,對variables給值,並執行function的呼叫(call)。
( 補充 : JS是直譯式語言的一種,而直譯式語言的特色就是「逐行( line by line )」執行。相對於編譯式語言「先編譯再執行」的方式。)
let a = 3; // a = 3
function area(s){
return s * s;
}
let b = area(a); // 調用area(a)
console.log(b);
延續上方的例子,程式碼會逐行進行給值,因此a會被先assign為3,
接著要assign值給b,就必須進行function call,調用函數area()。
目前 Global Execution Context 在 execution phase 的狀態:
object | value |
---|---|
global object | window |
this | window |
a | 3 |
area | function(){...} |
b | undefined |
到這裡Global scope會先停下來,
然後進入到Function Execution Context的creation phase...
JS會創造複數的Execution Context,而第二種就是Function Execution Context。
而每次的 function call ,JS引擎也都會創造一個Function Execution Context。
Function Execution Context 的 創造階段 creation phase :
和 Global Execution Context 的區別,引用文獻解釋的比較清楚 :
The Function Execution Context is similar to the Global Execution Context, but instead of creating the
global
object, it creates thearguments
object that contains a reference to all the parameters passed into the function.
(引用自 JavaScript Execution Context )
簡而言之,Execution Context在 creation phase 創造的不是window
,而是欲傳進函式的參數arguments
物件。
於是我們在 Function Execution Context 在 creation phase 會變成下列的狀態:
object | value |
---|---|
global object | arguments |
this | window |
s | undefined |
因為已經是Function Execution Context,global object會變為arguments,而參數s則被初始化為undefined。
然後進到 Function Execution Context 的 execution phase :
object | value |
---|---|
global object | arguments |
this | window |
s | 3 |
最後area(s)計算完成,便會回傳數值並assign給 b。
let a = 3;
function area(s){
return s * s;
}
let b = area(a);
console.log(b); // output: 9
從上面的敘述中,可以知道執行程式碼的時候創造了非常多的execution contexts,無論是Global EC或 Function EC 的執行,都會遵照被稱為 Call stack 資料結構。而資料結構就是之後文章的範疇了!
最後~
幫今天的文章畫重點:
window
,Function EC創造的Global Object則為arguments
。我寫了一張簡表,記憶JS的Execution Context執行和object的創建順序。
C. window obj. → scope ( follow closure ) → this → Hoisting
E. follow Call stack
C. scope chain → this → Hoisting
E. follow Call stack
之後整理專有名詞就可以更了解各個階段會出什麼事了
【如內文有誤還請不吝指教>< 並感謝閱覽至此的各位:D 】
---正文結束---
這篇是在發scope之前打好的,考慮了一下要不要跟鐵人賽發在一起,但實在太文不對題了所以還是獨立成一篇。
我覺得,發表文章在所有人都能看見的地方,是件蠻需要勇氣的事:(敬佩這裡所有的作者。