執行上下文和作用域的區別

原文:https://blog.bitsrc.io/understanding-execution-context-and-execution-stack-in-javascript-1c9ea8642dd0

執行上下文也叫執行環境?爲什麼呢就讓我這個英語zz來解釋下

context:環境; 上下文

執行環境:

執行環境中定義了變量或函數有權訪問的其他數據,決定了他們給各自行爲,每個執行環境都有一個與之關聯的變量對象,環境中定義的所有變量和函數都保持在這個對象中,雖然我們無法訪問到這個對象,但是解析器可以在處理數據的時候在後臺使用他 

 執行上下文類型:

  • 全局執行上下文 
  • 函數執行上下文 : 每當一個函數被調用時, 都會爲該函數創建一個新的上下文。每個函數都有它自己的執行上下文,不過是在函數被調用時創建的。函數上下文可以有任意多個。每當一個新的執行上下文被創建,它會按定義的順序,在執行棧中(將在後文討論)執行一系列步驟。
  • Eval 函數執行上下文 — 執行在 eval 函數內部的代碼也會有它屬於自己的執行上下文

 執行棧

執行棧,也就是在其它編程語言中所說的“調用棧”,是一種擁有 LIFO(後進先出)數據結構的棧,被用來存儲代碼運行時創建的所有執行上下文

後進先出:也就是隻有一個出口(數組開頭的位置),後進的執行上下文也是離空最近的,所以就先出

當 JavaScript 引擎第一次遇到你的腳本時,它會創建一個全局的執行上下文並且壓入當前執行棧。每當引擎遇到一個函數調用,它會爲該函數創建一個新的執行上下文並壓入棧的頂部。

引擎會執行那些執行上下文位於棧頂的函數。當該函數執行結束時,執行上下文從棧中彈出,控制流程到達當前棧中的下一個上下文

let a = 'Hello World!';

function first() {
  console.log('Inside first function');
  second();
  console.log('Again inside first function');
}

function second() {
  console.log('Inside second function');
}

first();
console.log('Inside Global Execution Context');

 

1:只有全局執行上下文

2:first()函數執行,執行棧中添加first()函數的執行上下文

3:在first函數執行的過程中Second函數執行了,second函數的執行上下文加入到執行棧中

4:Second函數執行完畢,移除執行棧

5:Frist()函數執行完畢移除執行棧

怎麼創建執行上下文?

在 JavaScript 代碼執行前,執行上下文將經歷創建階段。在創建階段會發生三件事:

  1. this 值的決定,即我們所熟知的 This 綁定
  2. 創建詞法環境組件。
  3. 創建變量環境組件。
ExecutionContext = {
  ThisBinding = <this value>,
  LexicalEnvironment = { ... },
  VariableEnvironment = { ... },
}

This 綁定:

在全局執行上下文中,this 的值指向全局對象。(在瀏覽器中,this引用 Window 對象)。

在函數執行上下文中,this 的值取決於該函數是如何被調用的。如果它被一個引用對象調用,那麼 this 會被設置成那個對象,否則 this 的值被設置爲全局對象或者 undefined(在嚴格模式下)

詞法環境變量環境

詞法環境變量環境內部有兩個組件:(1) 環境記錄器和 (2) 一個外部環境的引用

(1) 環境記錄器:存儲變量和函數聲明的實際位置

(2) 一個外部環境的引用:和它可以訪問其父級詞法環境(作用域)

但是有2種詞法環境變量環境類型一個是全局的一個是函數的分2中不同的情況

注意 — 對於函數環境聲明式(函數)環境記錄器還包含了一個傳遞給函數的 arguments 對象(此對象存儲索引和參數的映射)和傳遞給函數的參數的 length

詞法環境變量環境(區別

在 ES6 中,詞法環境組件和變量環境的一個不同就是前者被用來存儲函數聲明和變量(let 和 const)綁定,而後者只用來存儲 var 變量綁定。

例子:

let a = 20;
const b = 30;
var c;

function multiply(e, f) {
 var g = 20;
 return e * f * g;
}

c = multiply(20, 30);

解析:

// 全局
GlobalExectionContext = {

 
 // 詞法環境
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // 在這裏綁定標識符
      a: < uninitialized >,
      b: < uninitialized >,
      multiply: < func >
    }
    ThisBinding: <Global Object>, // this
    outer: <null> // 外部環境引用
  },
// 變量環境
  VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // 在這裏綁定標識符
      c: undefined,
    }
    outer: <null>  // 外部環境引用
  }
}
// 函數
FunctionExectionContext = {
 
  // 詞法環境
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // 在這裏綁定標識符
      Arguments: {0: 20, 1: 30, length: 2}, // 函數的專屬 arguments
    },
    ThisBinding: <Global Object>, // this
    outer: <GlobalLexicalEnvironment> // 外部環境引用
  },
// 變量環境
VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // 在這裏綁定標識符
      g: undefined
    },
    outer: <GlobalLexicalEnvironment> // 外部環境引用
  }
}

原作者更新了部分內容,將this bindng歸入詞法環境中了,

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章