为了知道那些常被拿来考观念的专有名词是哪里来的,
这篇要先整理 JS的 Execution Context!
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 的执行过程
所以Execution Context到底在做什么?
在执行过程中,JS里的物件会被初始化和给值。
假设现在JS要执行一个script,那么他就会:
先产生Execution Context进入创造阶段 creation phase完成creation phase,进入执行阶段 execution phase。在刚刚提到的定义里,可以发现定义里的execution context"s"是複数形,
由此可知会产生的execution context其实不只有一个,而程式码会执行的execution context分为两种:
并且,它们各自包含了 创造阶段 creation phase 和 执行阶段 execution phase,
所以这边先画个简表,我们现在有的资讯大概长这样:
而我们学习目标,就是要知道这段过程,哪个物件先创造? 什么时候被指派? 被指派给谁?
知道重点是什么就可以往下看了~
Global Execution Context
当初次 执行一个script时,JS引擎会创造第一种 execution context,叫 Global Execution Context。
然后先进入 创造阶段 creation phase :
window
object,或Node.js中的 global
object。)建立 scope (依照 closure 这个準则)。创建 this
object,并被绑定至 global object。将 variables
和 function
分配至记忆体,并初始化为 undefined。(这也是所谓的hoisting。)
讲太多抽象的概念不好理解,让我们假设一个求面积的程式码範例:
let a = 3;function area(s){ return s * s;}let b = area(a);console.log(b);
在这个阶段,各object会被初始化,也就是程式码会知道有这个object存在,但变数还不会被赋值。
因此 Global Execution Context在 creation phase 的状态如下:
接着,Global Execution Context 会来到 执行阶段 execution phase:
这时JS的script便会逐行被执行,对variables给值,并执行function的呼叫(call)。
( 补充 : JS是直译式语言的一种,而直译式语言的特色就是「逐行( line by line )」执行。相对于编译式语言「先编译再执行」的方式。)
let a = 3; // a = 3function 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 的状态:
到这里Global scope会先停下来,
然后进入到Function Execution Context的creation phase...
2. Function Execution Context
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 会变成下列的状态:
因为已经是Function Execution Context,global object会变为arguments,而参数s则被初始化为undefined。
然后进到 Function Execution Context 的 execution phase :
最后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 资料结构。而资料结构就是之后文章的範畴了!
最后~
帮今天的文章画重点:
Execution context即为程式码创造物件到执行的过程过程分为 Global EC 和 Function EC 两种。两者的区别为: Global EC创造的Global Object为window
,Function EC创造的Global Object则为arguments
。我写了一张简表,记忆JS的Execution Context执行和object的创建顺序。
Global EC
C. window obj. → scope ( follow closure ) → this → Hoisting
E. follow Call stack
Function EC
C. scope chain → this → Hoisting
E. follow Call stack
之后整理专有名词就可以更了解各个阶段会出什么事了
【如内文有误还请不吝指教>< 并感谢阅览至此的各位:D 】
---正文结束---
这篇是在发scope之前打好的,考虑了一下要不要跟铁人赛发在一起,但实在太文不对题了所以还是独立成一篇。
我觉得,发表文章在所有人都能看见的地方,是件蛮需要勇气的事:(敬佩这里所有的作者。