假裝是 JS 引擎,下面這段程式碼是怎麼被執行
var a = 1;
function test(){
console.log('1.', a);
var a = 7;
console.log('2.', a);
a++;
var a;
inner();
console.log('4.', a);
function inner(){
console.log('3.', a);
a = 30;
b = 200;
}
}
test();
console.log('5.', a);
a = 70;
console.log('6.', a);
console.log('7.', b);
每一個 log 出來的值,可以看上一篇中後段有寫答案
首先執行這個檔案,會先進入到 global 的 Execution Context ,先簡稱 EC
Variable Object 先簡稱 VO
step 1 進去 Execution Context
第一件事先找參數,但他不是 function , 所以沒有參數可以找
第二件事是找 function 宣告 ,找到一個名為 test 的 function
第三件事找變數宣告,找到一個 a ,並初始化為 undefined
global EC
global VO {
test: func,
a: undefined
}
step 2 執行程式碼
第一行 var a = 1;
a 被換成 1
global EC
global VO {
test: func,
a: 1
}
step 3 看到 test(); 並初始化 test 的 Variable Object
一樣第一件事先找參數,沒有參數
第二件事是找 function ,找到一個名為 inner 的 function
第三件事找變數宣告,找到一個 a ,並初始化為 undefined
test EC
test VO {
inner: func,
a: undefined
}
global EC
global VO {
test: func,
a: 1
}
step 4 執行 test function
一開始 console.log('1.', a);
,所以 a 就是 undefined
往下
var a = 7;
console.log('2.', a); // 這邊 a 的值從 undefined 變成 7
a++ // a 的值從 7 變成 8
再往下 inner();
所以又進入新的 Execution Context
step 5 初始化 inner 的 Variable Object
發現 inner 裡面沒有任何參數、function、變數
所以 inner 的 Variable Object 是空的
inner EC
inner VO {
}
test EC
test VO {
inner: func,
a: 8
}
global EC
global VO {
test: func,
a: 1
}
step 6 執行 inner function
一開始 console.log('3.', a);
因為 inner 的 Variable Object 是空的,沒有任何 a ,所以往上找
往上找,找到 test 的 Variable Object,裡面 a: 8
因此 console.log('3.', a);
log 出來 a 是 8
再來往下一行 a=30;
一樣因為 inner 的 Variable Object 是空沒有任何 a ,所以往上找 test VO
把 a: 8
改成 a: 30
再來往下一行 b = 200;
inner VO 沒有 b,往上 test VO 也沒有 b ,再往上 global VO 也沒有 b
所以只好在 global VO 放個 b ,然後值是 200
所以都找不到的話,就會在 global 新增一個值,變成全域變數
inner EC
inner VO {
}
test EC
test VO {
inner: func,
a: 30
}
global EC
global VO {
test: func,
a: 1
b: 200
}
step 7 執行完 inner function , inner 就變不見
test EC
test VO {
inner: func,
a: 30
}
global EC
global VO {
test: func,
a: 1
b: 200
}
step 8 回到 test 這個 function
inner()
下面一行是 console.log('4.', a);
此時 a 已經變 30
然後 test 這個 function 也執行完,可以消失了
global EC
global VO {
test: func,
a: 1
b: 200
}
step 9 回到 global
test()
下面一行是 console.log('5.', a);
所以 a 是 1
執行 a = 70;
global EC
global VO {
test: func,
a: 70
b: 200
}
繼續往下走 console.log('6.', a);
a 是 70
繼續往下走 console.log('7.', b);
b 是 200
全部執行完就 global EC 和 global VO 都不見就結束了