iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 16
0
Modern Web

跟著 YDKJS 作者 Kyle Simpson 打造全新 JavaScript Mindset系列 第 16

[day15] YDKJS (Scope) : 執行環境(Execution Context)的角色扮演遊戲(Executing time篇 )

  • 分享至 

  • xImage
  •  

var teacher = "Kyle";

function otherClass(){
	var teacher = "Suzy";
  	console.log("Welcome!");
}

function ask(){
  var question = "Why?";
  console.log(question);
}

otherClass();
ask();

我們昨天提到:

  1. 第一次 parser 的階段, compiler 只在乎 Identifier。
  2. parser 完成就配對完成所有的 Scope, 此時 line 10 知道是 block Scope (綠色)。
  3. 所有的 lexically scoped language (像是 JavaScript),
    決定所有的 lexical scopes and identifierscompile time
    不是 run time 決定
  4. 此時所有 var let const 之類的 Declaration 全部沒有意義,會移除,我們已經知道 Scope 規劃了。
  5. run time 會使用我們決定好的 lexically scoped 並產生 bytecode,也就是大家熟悉的 interpreter JavaScript 。

Run time 會使用我們決定好的 lexically scoped

line 1 : var teacher = "Kyle"
其實這邊有兩個 part :var teacher; teacher = "Kyle";

有玩過 JAVASCRIPT AST VISUALIZER
或是玩過 astexplorer

應該很可以體會:

  1. lexical scopes,identifiers 在 compile time (AST) 產生
  2. AST 沒有 值

astexplorer : var teacher = "Kyle"
astexplorer

再複習一個東西

LHS、RHS 的 L、R 就是這邊的左右,但其實不是方向的「左」「右」。
是取決於有沒有 target。

書(scope & closures/ch1.md)上寫, 你要思考 :

  • who's the target of the assignment(LHS)
  • who's the source of the assignment(RHS)

事實上只有 LHS ,一般來說 LHS 表示有 target , retrieve source (value)
不是 LHS 的全部都是 RHS ,也就是說,不是 target 就是 source。

後面盡量用 receiveing an assignment, target 的字眼來表示 LHS。
過於字面的文字沒有太多意義,理解比較重要。

舉例而言,

  • identifier var teacher 的 teacher ,可以 接收值(receiveing an assignment) ,所以是 target position
  • line 0 : console.log(question) 。 // 並沒有 target, 所以這是 soucre position。

Executing Code 時,就要組合 沒有 var 的 identifier a.k.a. 小球 ,還要知道每一行是什麼 position

遊戲裡面會有兩個角色:

  1. Scope manager

scope manager 他知道目前 Scope 的規劃書(AST)。

  1. JavaScript engin

Executing Code


首先,我們看到 line 1

這時候,對 JavaScript engin 來說,已經沒有 var(let,const also),只知道是變數(variable)

JavaScript engin 看到 變數 teacher 是一個 target reference 。

JavaScript engin:「嘿!紅色木桶的 Scope manager, 我有一個 變數 是一個 target reference ,叫做 teacher , 你有聽說過有一個叫做 teacher 的小球嗎?」

這邊的小球其實已經放入紅色桶子,所以當然
因為我們在 Run time 已經執行過一次對話了,那時候就制定小球和木桶的規劃。

Scope manager 這個階段基本上只回答 Yes or No。

紅色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

這邊等同 JavaScript engin 在問 :

JavaScript engin :「嗨! 紅色木桶的 Scope manager ,你有看過一個小球叫做 teacher 嗎? 如果有,可以給我嗎?」

然後 JavaScript engin 根據拿到的 Scope(規劃書),就把值("Kyle")寫入 identifier (紅色小球)。

訊息 : 「 回傳 JavaScript engin 把值寫入 identifier。 」

我們看到 line 3

其實這邊看不到 line 3 ~ 12, 因為這些 code 是給上一個階段的規劃書(Scope)用的,他們都是 identifier 。
這個階段反而關注 Executable Code.

我們看到 line 13

這邊要思考之前說的問題: 知道每一行是什麼 position 。
所以 line 13 是什麼 position ?

  • who’s the target of the assignment(LHS)
  • who’s the source of the assignment(RHS)

Ans: source position.

我們沒有對 line 13 做任何賦值 (not assigning to it),
然後之前還提過 不是 target 就是 source。

所以我們要拿東西出來

JavaScript engin:「嘿!紅色木桶的 Scope manager, 我有一個 identifier 是一個 source reference ,叫做 otherClass , 你有聽說過有一個叫做 otherClass 的小球嗎?」

紅色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

這時候 JavaScript engin 拿出一堆放在記憶體的東西,這邊的例子是一個 function。

function otherClass(){
	var teacher = "Suzy";
  	console.log("Welcome!");
}

訊息 : 「 回傳 JavaScript engin 一個 function , 而且是 藍色木桶裝的。 」

JavaScript engin 有時候可能拿到其他東西,比如 null, undefined,
如果拿到就會得到一個 TypeError 的錯誤。

不過這邊拿到 function ,沒有問題。

我們看到執行 function 的 line 4

這邊還是需要思考之前說的問題: 知道每一行是什麼 position 。
所以 line 4 是什麼 position ?

Ans: 看到 assignment , retrieve value, 所以是 target position 。

JavaScript engin:「嘿! 藍色木桶的 Scope manager, 我有一個 變數 是一個 target reference ,叫做 teacher , 你有聽說過有一個叫做 teacher 的小球嗎?」

這邊的小球其實已經放入藍色桶子,所以當然

Scope manager 這個階段基本上只回答 Yes or No。

藍色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

同樣的,這邊等同 JavaScript engin 在問 :

JavaScript engin :「嗨! 藍色桶子 的 Scope manager ,你有看過一個小球叫做 teacher 嗎? 如果有,可以給我嗎?」

然後 JavaScript engin 根據拿到的 Scope(規劃書),就把值("Suzy")寫入 identifier (藍色小球)。

訊息 : 「 回傳 JavaScript engin 把值寫入 identifier。 」

我們看到 line 5

這邊補充說明一下,雖然不是我們宣告的,
但是這邊有一個東西叫做 console ,也是 identifier。
它被內建在 JavaScript 中 (Build-in)。

JAVASCRIPT AST VISUALIZER :

astexplorer:

所以 line 5 是什麼 position ?
不是 target,所以是 source position

所以我們要拿東西出來

JavaScript engin:「嘿!藍色木桶的 Scope manager, 我有一個 identifier 是一個 source reference ,叫做 console , 你有聽說過有一個叫做 console 的小球嗎?」

藍色木桶的 Scope manager : 『No , 我沒看過它。』

沒看過的 identifier , Scope manager 會往外層尋找。

藍色木桶的 Scope manager : 『我幫你問看看 紅色木桶的 Scope manager 。』

紅色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

因為 console 被內建在 JavaScript 中。
console 是一個 object , 有一個 method 叫做 log 。

這時候 JavaScript engin 拿出放在記憶體的 method 並執行它。

訊息 : 「 回傳 JavaScript engin 一個 object , 而且是 紅色木桶裝的。 」

小總結

  1. 先找 是什麼 position
  • target position(LHS)
  • source position(RHS)
  1. 看 小球顏色 (identifier) 找木桶(Scope)。

我們回來 line 14

JavaScript engin:「嘿!紅色木桶的 Scope manager, 我有一個 identifier 是一個 source reference ,叫做 ask , 你有聽說過有一個叫做 ask 的小球嗎?」

紅色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

訊息 : 「 回傳 JavaScript engin 一個 function , 而且是 綠色木桶裝的。 」

我們看到執行 function 的 line 9

JavaScript engin:「嘿! 綠色木桶的 Scope manager, 我有一個 變數 是一個 target reference ,叫做 question , 你有聽說過有一個叫做 question 的小球嗎?」

綠色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

訊息 : 「 回傳 JavaScript engin 把值寫入 identifier。 」

我們看到執行 function 的 line 10

JavaScript engin:「嘿!綠色木桶的 Scope manager, 我有一個 identifier 是一個 source reference ,叫做 console , 你有聽說過有一個叫做 console 的小球嗎?」

綠色木桶的 Scope manager : 『No , 我沒看過它。』

綠色木桶的 Scope manager : 『我幫你問看看 紅色木桶的 Scope manager 。』

紅色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

訊息 : 「 回傳 JavaScript engin 一個 object , 而且是 紅色木桶裝的。 」

問題來了,然後怎麼辦?
再問一次啊~

JavaScript engin:「嘿!綠色木桶的 Scope manager, 我有一個 identifier 是一個 source reference ,叫做 question , 你有聽說過有一個叫做 question 的小球嗎?」

綠色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

訊息 : 「 回傳 JavaScript engin 一個 值 , 而且是 綠色木桶裝的。 」

順帶一提,因為是 source reference ,所以拿出來的東西馬上就執行了。

看起來就會是 :ask() // "Why?"

總結

把上面分散的對話一次完成,如果不確定可以拉上去看。

首先,我們看到 line 1

JavaScript engin:「嘿!紅色木桶的 Scope manager, 我有一個 變數 是一個 target reference ,叫做 teacher , 你有聽說過有一個叫做 teacher 的小球嗎?」

紅色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

訊息 : 「 回傳 JavaScript engin 把值寫入 identifier。 」

我們看到 line 3

// Skip line 3 ~ 12

我們看到 line 13

JavaScript engin:「嘿!紅色木桶的 Scope manager, 我有一個 identifier 是一個 source reference ,叫做 otherClass , 你有聽說過有一個叫做 otherClass 的小球嗎?」

訊息 : 「 回傳 JavaScript engin 一個 function , 而且是 藍色木桶裝的。 」

我們看到執行 function 的 line 4

JavaScript engin:「嘿! 藍色木桶的 Scope manager, 我有一個 變數 是一個 target reference ,叫做 teacher , 你有聽說過有一個叫做 teacher 的小球嗎?」

藍色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

訊息 : 「 回傳 JavaScript engin 把值寫入 identifier。 」

我們看到 line 5

JavaScript engin:「嘿!藍色木桶的 Scope manager, 我有一個 identifier 是一個 source reference ,叫做 console , 你有聽說過有一個叫做 console 的小球嗎?」

藍色木桶的 Scope manager : 『No , 我沒看過它。』
藍色木桶的 Scope manager : 『我幫你問看看 紅色木桶的 Scope manager 。』

紅色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

訊息 : 「 回傳 JavaScript engin 一個 object , 而且是 紅色木桶裝的。 」

我們回來 line 14

JavaScript engin:「嘿!紅色木桶的 Scope manager, 我有一個 identifier 是一個 source reference ,叫做 ask , 你有聽說過有一個叫做 ask 的小球嗎?」

紅色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

訊息 : 「 回傳 JavaScript engin 一個 function , 而且是 綠色木桶裝的。 」

我們看到執行 function 的 line 9

JavaScript engin:「嘿! 綠色木桶的 Scope manager, 我有一個 變數 是一個 target reference ,叫做 question , 你有聽說過有一個叫做 question 的小球嗎?」

綠色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

訊息 : 「 回傳 JavaScript engin 把值寫入 identifier。 」

JavaScript engin:「嘿!綠色木桶的 Scope manager, 我有一個 identifier 是一個 source reference ,叫做 console , 你有聽說過有一個叫做 console 的小球嗎?」

綠色木桶的 Scope manager : 『No , 我沒看過它。』

綠色木桶的 Scope manager : 『我幫你問看看 紅色木桶的 Scope manager 。』

紅色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

訊息 : 「 回傳 JavaScript engin 一個 object , 而且是 紅色木桶裝的。 」

我們看到執行 function 的 line 10

JavaScript engin:「嘿!綠色木桶的 Scope manager, 我有一個 identifier 是一個 source reference ,叫做 question , 你有聽說過有一個叫做 question 的小球嗎?」

綠色木桶的 Scope manager : 『Yes , 我知道它,拿去吧!』

訊息 : 「 回傳 JavaScript engin 一個 值 , 而且是 綠色木桶裝的。 」

// 全部結束。


上一篇
[day14] YDKJS (Scope) : 執行環境 (Execution Context)的角色扮演遊戲(compile time篇)
下一篇
[day16] YDKJS (Scope) : Lexical Scope Review(投影片當動畫),Error 種類
系列文
跟著 YDKJS 作者 Kyle Simpson 打造全新 JavaScript Mindset31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言