Jeff的隨手筆記

學習當一個前端工程師

0%

『JavaScript 基礎』了解function底層運作邏輯以及Scope

Imgur

這是一門在Udemy 課程,是同學介紹的。主要是因為想要運用到過年前這段時間好好的增進自己的JavaScript的基礎能力,讓自己能往前端工程師更近一步。主要還是會以筆記的形式做呈現!


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

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

1
2
3
4
5
6
7
function b() {

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

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

Imgur

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

Imgur

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

Imgur

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。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
3
1
2
undefined

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
function b() {
console.log(myVar)
}

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

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

結果會是:

1
2
3
1
2
1

為什麼第三個不是not defined ?

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

Imgur

雖然程式執行的過程中會先執行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

lexical environment(詞彙環境)

在JavaScript中,他所代表的的是:今天這段code在memory的位子
所以不需要去考慮他們在code的順序,因為執行的順序是跟他們被 invoked 有關