請說明以下程式碼會輸出什麼,以及盡可能詳細地解釋原因。
var a = 1
function fn(){
console.log(a)
var a = 5
console.log(a)
a++
var a
fn2()
console.log(a)
function fn2(){
console.log(a)
a = 20
b = 100
}
}
fn()
console.log(a)
a = 10
console.log(a)
console.log(b)
答案
undefined
5
6
20
1
10
100
因為程式運作時會先處理宣告的變數和函式,變數被宣告時會被先指定為 undefined
,所以在賦值之前使用都會取到其值為 undefined
- globalEC 編譯
globalEC: { VO: { a: undefined, fn: function, }, scopeChain: [globalEC.VO] }
- globalEC 執行
a = 1
找到 globalEC.VO 裡的 a 賦值globalEC: { VO: { a: 1, fn: function, }, scopeChain: [globalEC.VO] }
- fnEC 編譯,第二次出現的
var a
因為已經宣告過了所以不用處理fnEC: { AO: { a: undefined, fn2: funciton, }, scopeChain: [fnEC.AO + globalEC.VO] }
- fnEC 執行,
a. 第一行的
console.log(a)
,因為此時的 fnEC.AO 中的a
為undefined
,所以輸出undefined
b. 第二行為a = 5
,找到 fnEC.AO 中的a
更新其值為5
c. 第一行的fnEC: { AO: { a: 5, fn2: funciton, }, scopeChain: [fnEC.AO + globalEC.VO] }
console.log(a)
,因為此時的 fnEC.AO 中的a
為5
,所以輸出5
d. 第四行a++
,fnEC.AO 中的a
更新其值為6
``` fnEC: { AO: { a: 6, fn2: funciton, }, scopeChain: [fnEC.AO + globalEC.VO] } - fn2EC 編譯 ,因為裡面第二行和第三行的
a = 20
和b = 100
都只是單純的賦值,所以 fn2EC.AO 為空的fn2EC: { AO: { }, scopeChain: [fn2EC.AO + fnEC.AO + globalEC.VO] }
- fn2 執行
a.
console.log(a)
: 因為 fn2EC.AO 找不到a
所以沿著scopeChain
網上找。在 fnEC.AO 找到a
的值為6
輸出6
b.a = 20
: 因為 fn2EC.AO 找不到a
所以沿著scopeChain
往上找。在 fnEC.AO 找到a
,將a
更新為20
。c.fnEC: { AO: { a: 20, fn2: funciton, }, scopeChain: [fnEC.AO + globalEC.VO] }
b = 100
: 因為 fn2EC.AO 找不到b
所以沿著scopeChain
往上找都在不到,所以在 globalEC 宣告一個變數b
其值為100
globalEC: { VO: { a: 1, b: 100, fn: function, }, scopeChain: [globalEC.VO] }
fn2()
執行完將fn2EC
消除,換執行下一行的console.log(a)
,因為此時 fnEC.AO 中的值已經被更改為20
,所以輸出20
fn()
執行完畢,將fnEC
消除,換執行下一行的console.log(a)
。此時 globalEC.AO 中的值為1
,所以輸出1
a = 10
: 在 globalEC.VO 中找到a
,將a
更新為10
。globalEC: { VO: { a: 10, b: 100, fn: function, }, scopeChain: [globalEC.VO] }
consloe.log(a)
: 在 globalEC.VO 中找到a
的值為10
, 輸出10
console.log(b)
: 在 globalEC.VO 中找到b
的值為100
, 輸出100