深入學習js之——執行上下文#7

MagicalLouis發表於2019-03-15

深入學習js系列是自己階段性成長的見證,希望通過文章的形式更加嚴謹、客觀地梳理js的相關知識,也希望能夠幫助更多的前端開發的朋友解決問題,期待我們的共同進步。

如果覺得本系列不錯,歡迎點贊、評論、轉發,您的支援就是我堅持的最大動力。


《深入學習js之——執行上下文棧》中說過,當JavaScript程式碼執行一段可執行程式碼(executable code)時,會建立對應的執行上下文(execution context)

對於每一個執行上下文,都有三個重要的屬性:

變數物件(Variable object VO) 作用域鏈(Scope chain) this

本文我們結合著這三個部分的內容,講講執行上下文的具體處理過程。

思考題

《深入學習js之——詞法作用域和動態作用域》中,提出這樣一道思考題:

// 思考題一:
var scope = "global scope";
function checkscope(){
  var scope = "local scope";
  function f(){
    return scope;
  }
  return f();
}
checkscope();

// 思考題二:
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
}
checkscope()();
複製程式碼

兩段程式碼都會列印local scope,但是還是有些許差異的,本文就詳細的解析執行上下文棧執行上下文的具體變化過程。

具體分析

我們分析第一段程式碼:

var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();
複製程式碼

執行過程如下:

1、執行全域性程式碼,建立全域性執行上下文,全域性上下文被壓入執行上下文棧

ECStack = [
  globalContext
];
複製程式碼

2、全域性上下文初始化

globalContext = {
  VO: [global],
  Scope: [globalContext.VO],
  this: globalContext.VO
}
複製程式碼

2、初始化的同時,checkscope 函式被建立,儲存作用域鏈到函式內部的屬性[[scope]]

checkscope.[[scope]] = [
  globalContext.VO
];
複製程式碼

3、執行checkScope 函式,建立checkScope 函式執行上下文,checkScope 函式執行上下文被壓入執行上下文棧:

ECStack = [
  checkscopeContext,
  globalContext
];
複製程式碼

4、checkscope 函式執行上下文初始化:

1.複製函式 [[scope]] 屬性建立作用域鏈, 2.用 arguments 建立活動物件, 3.初始化活動物件,即加入形參、函式宣告、變數宣告, 4.將活動物件壓入 checkscope 作用域鏈頂端,

同時 f 函式被建立,儲存作用域鏈到 f 函式的內部屬性[[scope]]

checkscopeContext = {
  AO: {
      arguments: {
        length: 0
      },
      scope: undefined,
      f: reference to function f(){}
  },
  Scope: [AO, globalContext.VO],
  this: undefined
}
複製程式碼

5、執行f函式,建立 f 函式執行上下文,f 函式執行上下文被壓入執行上下文棧

  ECStack = [
    fContext,
    checkscopeContext,
    globalContext
  ]
複製程式碼

6、f 函式執行上下文初始化, 以下跟第 4 步相同:

1.複製函式 [[scope]] 屬性建立作用域鏈 2.用 arguments 建立活動物件 3.初始化活動物件,即加入形參、函式宣告、變數宣告 4.將活動物件壓入 f 作用域鏈頂端

  fContext = {
    AO: {
        arguments: {
            length: 0
        }
    },
    Scope: [AO, checkscopeContext.AO, globalContext.VO],
    this: undefined
  }
複製程式碼

7、f 函式執行,沿著作用域鏈查詢 scope 值,返回 scope 值

8、f 函式執行完畢,f 函式上下文從執行上下文棧中彈出

ECStack = [
  checkscopeContext,
  globalContext
]
複製程式碼

9、checkscope 函式執行完畢,checkscope 執行上下文從執行上下文棧中彈出

ECStack = [
  globalContext
]
複製程式碼

深入學習JavaScript系列目錄

歡迎新增我的個人微信討論技術和個體成長。

深入學習js之——執行上下文#7
歡迎關注我的個人微信公眾號——指尖的宇宙,更多優質思考乾貨

深入學習js之——執行上下文#7

相關文章