中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

一篇文章弄懂javascript中的執行棧與執行上下文

發布時間:2020-10-22 22:20:32 來源:腳本之家 閱讀:129 作者:我聽莫扎特 欄目:web開發

前言

作為一個前端開發人員,弄清楚JavaScript的執行上下文有助于我們理解js中一些晦澀的概念,比如閉包,作用域,變量提升等等。

執行棧

執行棧用于存儲代碼執行期間創建的所有執行上下文。具有FILO接口,也被稱為調用棧。
當JavaScript代碼被運行的時候,會創建一個全局上下文,并push到當前執行棧。之后當發生函數調用的時候,引擎會為函數創建一個函數執行上下文并push到棧頂。引擎會先執行調用棧頂部的函數,當函數執行完成后,當前函數的執行上下文會被移除當前執行棧。并移動到下一個上下文。

let a = 'Hello'

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')

一篇文章弄懂javascript中的執行棧與執行上下文

執行上下文

我們可以理解為執行上下文是js代碼被解析和執行時所在環境的抽象概念。
JavaScript的執行上下文分為三種類型:

  • 全局執行上下文:最基本的上下文,只有一個。創建了一個全局對象(eg:瀏覽器中的window),將this指向全局對象。
  • 函數執行上下文:每次調用函數都會創建一個函數上下文。函數上下文可以存在無數個。
  • Eval函數執行上下文:運行在eval函數中的代碼會有一個自己的執行上下文(本文不討論)。

執行上下文的創建

創建執行上下文又可以分為兩個階段: 1. 創建階段 2. 執行階段

創建階段

在創建階段,JavaScript引擎會創建LexicalEnvironment(詞法環境)組件,VariableEnvironment(變量環境)組件以及this綁定(在全局上下文中,this指向全局對象。在函數執行上下文中,this取決與函數在哪里被調用。)

Lexical  Environment(詞法環境)

ES2015規范對詞法環境的描述

我們可以理解為詞法環境是一種包含標識符(變量/函數的名稱)和變量(實際對象:函數/原始值/數組對象等)映射的數據結構。

每個詞法環境由兩部分組成:Environment Record環境記錄(存儲變量和函數聲明的實際位置)和對外部環境的引用(可以訪問其外部詞法環境)

環境記錄分為兩種:

  • Declarative environment record(聲明性環境記錄): 存儲變量和函數聲明。
  • Object environment record(對象環境記錄):全局詞法環境。除了變量和函數聲明外,對象環境記錄還存儲全局綁定對象。

tips:對于函數執行上下文來說,環境記錄還包含了一個arguments對象,包含了傳遞給函數的索引和參數之間的映射以及函數參數的數量。

例如:

function foo(a, b) {
  var c = a + b
}

// argument object
Arguments: {0: 2, 1: 3, length: 2}

VariableEnvironment(變量環境)

變量環境也是一個詞匯環境,因此它具有上面定義的詞法環境的所有屬性和組件。在ES6中,LexicalEnvironment組件和VariableEnvironment組件之間的一個區別是前者用于存儲函數聲明和變量let和const綁定,而后者僅用于存儲變量var綁定。

執行階段

在執行階段,會完成對所有變量的分配,代碼也會被最終執行。執行上下文的代碼會被分成兩個階段:

  1. 進入執行上下文
  2. 代碼執行
let a = 20
const b = 30
var c

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

c = multiply(20, 30)

當上面的代碼被執行的時候,JavaScript引擎會創建一個全局上下文來執行全局代碼。

此時的全局上下文:

GlobalExectionContext = {  // 全局上下文
  LexicalEnvironment: {  // 詞法環境
    EnvironmentRecord: {  // 環境記錄
      type: 'Object', // 類型
      // 標識符
      a: <uninitialized>,
      b: <uninitialized>,
      multiply: <func>
    },
    outer: <null>, // 對外部環境引用
  },
  VariableEnvironment: { // 變量環境
    EnvironmentRecord: {  // 環境記錄
      type: 'Object',
      c: undefined
    },
    outer: <null>, // 對外部環境引用
  },
  ThisBinding: <Global Object>  // this綁定
}

在執行階段,變量會被賦值,此時的全局上下文變成:

GlobalExectionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      type: 'Object',
      a: 20,
      b: 30,
      multiply: <func>
    },
    outer: <null>
  },
  VariableEnvironment: {
    EnvironmentRecord: {
      type: 'Object',
      c: undefined
    }
    outer: <null>
  },
  ThisBinding: <Global Object>
}

當JavaScript引擎遇到函數multiply(20, 30)的時候,會創建一個新的函數上下文:

FunctionExectionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      type: 'Declarative',
      arguments: {
        0: 20,
        1: 30,
        length: 2
      }
    },
    outer: <GlobalLexicalEnvironment>
  },
  VariableEnvironment: {
    EnvironmentRecord: {
     Type: "Declarative",
     g: undefined
    },
    outer: <GlobalLexicalEnvironment>,
  },
  thisBinding: <Global Object or undefined>
}

之后執行上下文會進入執行階段, 此時的函數上下文:

FunctionExectionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      type: 'Declarative',
      arguments: {
        0: 20,
        1: 30,
        length: 2
      }
    },
    outer: <GlobalLexicalEnvironment>
  },
  VariableEnvironment: {
    EnvironmentRecord: {
     Type: "Declarative",
     g: 20
    },
    outer: <GlobalLexicalEnvironment>,
  },
  thisBinding: <Global Object or undefined>
}

當函數執行完畢后。會返回一個值并賦值給變量c,全局上下文被更新。更新完成后,代碼執行完畢,程序結束。

參考文章

Understanding Execution Context and Execution Stack in Javascript

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西峡县| 三明市| 江阴市| 合阳县| 凉城县| 兴和县| 施甸县| 莱阳市| 龙江县| 张家口市| 玉门市| 黄梅县| 依兰县| 县级市| 株洲市| 西藏| 肇州县| 竹溪县| 白银市| 从化市| 疏附县| 公主岭市| 罗源县| 灵川县| 潼关县| 两当县| 达日县| 夹江县| 阳江市| 德化县| 印江| 旬阳县| 中方县| 宁德市| 襄垣县| 仲巴县| 芦山县| 辽源市| 靖远县| 社旗县| 民丰县|