這個是今天的範例,估計會一直看到它
var teacher = "Kyle";
function otherClass(){
var teacher = "Suzy";
console.log("Welcome!");
}
function ask(){
var question = "Why?";
console.log(question);
}
otherClass();
ask();
遊戲裡面會有兩個角色:
scope manager 製造 有顏色的桶子(buckets),有顏色的小球 (marbles)。
然後 compiler 會問要怎麼丟球分配。
( processing the JavaScript program.)
這兩個角色溝通完,會產生一個計畫 (plan)。
真正執行產生 bytecode 的時候,會依照這份計畫執行。
前置道具:
紅色:global
藍色:不是 global 的 block 顏色
綠色:反正 block 顏色不能重複
... 其他顏色 ,etc.identifier 就是我們的小球
Scope 就是我們的桶子昨天提過
Declaration
,可以確認:
JavaScript ast 產生器
[day13] YDKJS (Scope) : JavaScript 是 parser language ? 不是 interpreter 嗎?
line 1
。這時候,因為是第一次 parsed(為了 AST 產生),會有一個 Scope manager 創造一個 紅色桶子。
訊息:「Scope manager 已經創造一個 紅色桶子。」
compiler 看到 var teacher
是一個 Variable Declaration。
compiler:「嘿!
紅色桶子 的 manager
, 你有聽說過有一個東西(Identifier)叫做teacher
嗎?」
compiler 問 紅色桶子的 manager 有沒有一個 Identifier 叫做 teacher
。
紅色桶子 的 manager 看一下,此時還沒有出現這個東西 。
所以 紅色桶子 的 manager 會這樣回覆 :
紅色桶子 的 manager : 『我沒有聽過耶。我這邊有一個紅色桶子!把那個紅色小球丟進來吧!』
然後我們把這個小球丟進去 紅色桶子。
這時候做的事情是「規劃 執行環境 (Execution Context)」。
line 3
。compiler 看到 function otherClass()
是一個 function Declaration。
compiler 又會問:有這個東西存在嗎?
compiler:「嘿!
紅色桶子 的 manager
, 你有聽說過有一個東西(Identifier)叫做otherClass
嗎?」
紅色桶子 的 manager : 『我沒有聽過耶。』
紅色桶子 的 manager : 『我這邊有一個紅色桶子!把那個紅色小球(Identifier)丟進來吧!』
這時候 compiler 才會知道整個 function otherClass()
是一個 紅色桶子。
紅色桶子正在裝 function otherClass()
。
可是又遇到一個 { .. } 的 block ,
這時候,裡面就要用其他顏色的桶子裝小球(Identifier),
因為 function 裡面是一個 block,所以要換桶子(Scope)。
可以參考,書(scope & closures/ch2.md)上這張圖的感覺(橘色的 2 就是我們說的藍色桶子):
這時候,有一個 Scope manager 創造一個 藍色桶子。
訊息:「Scope manager 已經創造一個 藍色桶子。」
補充: 昨天有請大家先看書。
Contextual Rules 的 { .. } Curly Braces。
line 4
。compiler 在藍色桶子
看到 var teacher
是一個 Variable Declaration。
compiler:「嘿!
藍色桶子 的 manager
, 你有聽說過有一個東西(Identifier)叫做teacher
嗎?」
因為不同顏色桶子的 manager 不一樣,所以 藍色桶子 的 manager
還沒有看過。
藍色桶子 的 manager : 『我沒有聽過耶。』
藍色桶子 的 manager : 『我這邊有一個藍色桶子!把那個藍色小球(Identifier)丟進來吧!』
雖然名稱一樣,但是不同桶子的 manager 是不同人,所以不認識。
名稱一樣
,但是Scope 不一樣
的狀況,或是 同名 Identifier
又稱作 shadowing
。也就是藍色的 Scope manager 不會知道外面還有一個
紅色的 同名 小球(global shadowing identifier)
。
小小總結:
line 5
。line 5 不是一個 Declaration,所以跳過。
而且因為藍色桶子內都執行過了,所以 compiler 離開藍色桶子。
line 8
。此時,compiler 已經離開藍色桶子,回到紅色桶子的區域。
compiler 看到 function ask()
是一個 function Declaration。
compiler:「嘿!
紅色桶子 的 manager
, 你有聽說過有一個東西(Identifier)叫做ask
嗎?」
紅色桶子 的 manager : 『我沒有聽過耶。』
紅色桶子 的 manager : 『我這邊有一個紅色桶子!把那個紅色小球(Identifier)丟進來吧!』
這時候 compiler 才知道整個 function ask()
是一個 紅色桶子。
紅色桶子正在裝 function ask()
。
可是又遇到一個 { .. } 的 block ,
這時候,裡面就要用其他顏色的桶子裝小球(Identifier),
因為 function 裡面是一個 block,所以要換桶子(Scope)。
這時候,有一個 Scope manager 創造一個桶子,可是藍色已經分配出去了
,所以這邊改用綠色。
可以參考,書(scope & closures/ch2.md)上這張圖的感覺(橘色的 2 就是我們說的綠色桶子):
訊息:「Scope manager 已經創造一個 綠色桶子。」
line 9
。compiler 在 綠色桶子
看到 var question
是一個 Variable Declaration。
compiler:「嘿!
綠色桶子 的 manager
, 你有聽說過有一個東西(Identifier)叫做question
嗎?」
因為不同顏色桶子的 manager 不一樣,所以 綠色桶子 的 manager
還沒有看過。
綠色桶子 的 manager : 『我沒有聽過耶。』
綠色桶子 的 manager : 『我這邊有一個綠色桶子!把那個綠色小球(Identifier)丟進來吧!』
小小總結:
把上面分散的對話一次完成,如果不確定可以拉上去看。
line 1
。訊息:「Scope manager 已經創造一個 紅色桶子。」
compiler:「嘿!
紅色桶子 的 manager
, 你有聽說過有一個東西(Identifier)叫做teacher
嗎?」紅色桶子 的 manager : 『我沒有聽過耶。我這邊有一個紅色桶子!把那個紅色小球丟進來吧!』
line 3
。compiler:「嘿!
紅色桶子 的 manager
, 你有聽說過有一個東西(Identifier)叫做otherClass
嗎?」
紅色桶子 的 manager : 『我沒有聽過耶。』
紅色桶子 的 manager : 『我這邊有一個紅色桶子!把那個紅色小球(Identifier)丟進來吧!』
因為 function 裡面是一個 block,所以要換桶子(Scope)。
訊息:「Scope manager 已經創造一個 藍色桶子。」
line 4
。compiler:「嘿!
藍色桶子 的 manager
, 你有聽說過有一個東西(Identifier)叫做teacher
嗎?」
因為不同顏色桶子的 manager 不一樣,所以 藍色桶子 的 manager
還沒有看過。
藍色桶子 的 manager : 『我沒有聽過耶。』
藍色桶子 的 manager : 『我這邊有一個藍色桶子!把那個藍色小球(Identifier)丟進來吧!』
line 5
。line 5 不是一個 Declaration,所以跳過。
而且因為藍色桶子內都執行過了,所以 compiler 離開藍色桶子。
line 8
。此時,compiler 已經離開藍色桶子,回到紅色桶子的區域。
compiler:「嘿!
紅色桶子 的 manager
, 你有聽說過有一個東西(Identifier)叫做ask
嗎?」
紅色桶子 的 manager : 『我沒有聽過耶。』
紅色桶子 的 manager : 『我這邊有一個紅色桶子!把那個紅色小球(Identifier)丟進來吧!』
因為 function 裡面是一個 block,所以要換桶子(Scope)。
這時候,有一個 Scope manager 創造一個桶子,可是藍色已經分配出去了,所以這邊改用綠色。
訊息:「Scope manager 已經創造一個 綠色桶子。」
line 9
。compiler:「嘿!
綠色桶子 的 manager
, 你有聽說過有一個東西(Identifier)叫做question
嗎?」
因為不同顏色桶子的 manager 不一樣,所以 綠色桶子 的 manager
還沒有看過。
綠色桶子 的 manager : 『我沒有聽過耶。』
綠色桶子 的 manager : 『我這邊有一個綠色桶子!把那個綠色小球(Identifier)丟進來吧!』
line 10
知道是 block Scope (綠色)。lexical scopes
and identifiers
在 compile time
,不是 run time 決定
。var let const
之類的 Declaration 全部沒有意義,會移除,我們已經知道 Scope 規劃了。Run Time 下集待續 :P