[進階 js 06] 體驗 JS 引擎的一天,理解 Execution Context 與 Variable Object


Posted by tzutzu858 on 2021-03-24

假裝是 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 都不見就結束了










Related Posts

Java Stream intermediate operations are lazily executed

Java Stream intermediate operations are lazily executed

Day06 從案例看原生 History API (中)

Day06 從案例看原生 History API (中)

七天打造自己的 Google Map 應用入門 - Day05

七天打造自己的 Google Map 應用入門 - Day05


Comments