[進階 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

【MySQL】透過 FIELD 函式自訂排序

【MySQL】透過 FIELD 函式自訂排序

Kotlin 練功場 - Android 組

Kotlin 練功場 - Android 組

JSON-server建一支RESTful API

JSON-server建一支RESTful API


Comments