iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0
自我挑戰組

重新複習JavaScript系列 第 9

[Day -9] 了解function底層運作邏輯

  • 分享至 

  • xImage
  •  

我們都知道,在JavaScript 要執行一段函式只需要在函式的最後加上()就可以了,我們把執行函式的執行這個動作稱做invoke。

下面有一段簡單的code,我們用這段code來解釋原理:

function b() {

}
function a() {
  b()
}
a()

當我們執行上述code 時,我們會先創建一個global execution context,這時候會一併建立this、global object (如果是在瀏覽器則是建立window object)

當我執行到a()時,除了會建立a() execution context並且會被放置在execution stack中。

如果我在執行這個 execution context 時, invoke 另一個 function時,它就會在那個地方停住並且創建另一個 execution context。

execution stack 最上面的會是正在執行的。任何時候在JavaScript中 invoke a function ,都會創建一個execution context 並放入execution stack。每一個execution context都擁有自己的空間 for variables and functions。

我們來總結一下:

每一次我們調用function時,該function都會創建一個新的execution context (第一階段創建變數並且先讓每個變數值放入undefined,第二階段才會把我們要給這個變數的值放到裡面。’this’這個特殊變數也會一起創建),並把這個新的execution context放到 stack的最上面(stack為後進先出,最上面的會先執行,synchronously)然後完成後他就會popped off。


基礎的原理理解完後,來看一個稍微進階一點的:

function b() {
  var myVar
  console.log(myVar)
}

function a() {
  var myVar = 2
  console.log(myVar)
  b()
}

var myVar = 1
console.log(myVar)
a()

結果是:

1
2
undefined

疑?為什麼在三個會是undefined,原因就在於剛剛我們有提到:每一個execution context都擁有自己的空間 for variables and functions,因為這個原因,不同 execution context 中的變數是不會互相影響的。

所以這個案例來說,我在function b 裡面有在宣告一個名為myVar 的變數,因此只要在這個function裡面所有使用到myVar都是會以這次宣告為主。

但如果這時候我是使用myVar而不是宣告呢?

function b() {
  console.log(myVar)
}

function a() {
  var myVar = 2
  console.log(myVar)
  b()
}

var myVar = 1
console.log(myVar)
a()

結果會是:

1
2
1

為什麼第三個不是not defined ?

這是因為在未宣告新的變數的情況下,在該execution context中JavaScript engine找不到這個變數,它就會往它的外層(Outer Environment)去尋找。

雖然程式執行的過程中會先執行global execution context(myVar = 1),接著執行function a(myVar = 2),最後才執行function b。但是對於function b來說,它的outer environment就是最外層的global environment,這就是他的結果是1不是2的原因


解釋一下兩個名詞:

scope chain(作用域鏈)

Scope Chain就是在找變數的過程中,從內層找到外層,直到最外面的global environment的這條鍊,就叫做Scope Chain。

outer environment(外部環境)

每個 execution context 都會對 outer environment 做引用,什麼時候會做這項動作:呼叫一個變數但在execution context中沒有時,它會往它的outer environment去找。

但並不是直接看code的順序,而是要看lexical environment


這次真的是結束了,在排前面這幾篇順序時我很猶豫,scope 跟 hoistting 是否真的要擺在這麼前面,原本的打算是要放在 data types 後面,但在整理自己之前的文章還有筆記時發現了這篇,覺得很重要想要放進來,但這樣兩篇function中間會隔著兩篇,我很不喜歡XD因此就變成現在的順序。

希望大家喜歡這樣的排序!


上一篇
[Day -8] 函式(function)
下一篇
[Day -10] 運算子(Operator)(1)
系列文
重新複習JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言