日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

从 ECMAScript 6 角度谈谈执行上下文

發布時間:2023/12/24 windows 35 coder
生活随笔 收集整理的這篇文章主要介紹了 从 ECMAScript 6 角度谈谈执行上下文 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

大家好,我是歸思君

起因是最近了解JS執行上下文的時候,發現很多書籍和資料,包括《JavaScript高級程序設計》、《JavaScript權威指南》和網上的一些博客專欄,都是從 ES3 角度來談執行上下文,用ES6規范解讀的比較少,所以想從ES6的角度看一下執行上下文。

下面我嘗試用ECMAScript 6規范文檔,來聊聊執行上下文,文章主要從這幾個方面介紹:

  • ES6規范中的詞法環境
  • ES6規范中定義的執行上下文結構
  • 從ES6規范看實際代碼的執行流程

一、 什么是執行上下文

咱們先來看看 ES6 中怎么定義執行上下文的:

An execution context is a specification device that is used to track the runtime evaluation of code by an ECMAScript implementation. At any point in time, there is at most one execution context that is actually executing code. This is known as the running execution context.
A stack is used to track execution contexts. The running execution context is always the top element of this stack. A new execution context is created whenever control is transferred from the executable code associated with the currently running execution context to executable code that is not associated with that execution context. The newly created execution context is pushed onto the stack and becomes the running execution context.

執行上下文是一種規范類型,用于跟蹤 ECMAScript 實現(也就是 JavaScript 語言)代碼的執行狀態。在任意(代碼執行)的時間點中,最多有一個執行上下文在實際執行代碼。這稱為運行執行上下文。

堆棧用于跟蹤執行上下文。正在運行的執行上下文始終是該堆棧的頂部元素。每當控制從與當前運行的執行上下文關聯的可執行代碼轉移到不與該執行上下文關聯的可執行代碼時,就會創建新的執行上下文。新創建的執行上下文被壓入堆棧并成為正在運行的執行上下文。

為什么執行上下文是一種“specification device”呢?
因為 EcmaScript 實際上是由 ECMA(European Computer Manufactures Association, 歐洲計算機制造協會) 制定的一種語言規范,而像 JavaScript、Adobe ActionScript 都是 ECMAScript 的一種實現,所以上述描寫中的執行上下文,是一種在規范下的定義。
從上面的定義可知:

  • 執行上下文是 JavaScript 執行代碼時的運行環境
  • 跟蹤執行上下文的堆棧是執行上下文調用棧(call stack),正在運行的執行上下文的是棧頂元素
  • 在執行上下文切換新的可執行代碼時,會創建新的執行上下文(函數調用)

在分析執行上下文時,先來了解一下詞法環境的概念:

二、Lexical Environments(詞法環境)

A Lexical Environment is a specification type used to define the association of Identifiers to specific variables and functions based upon the lexical nesting structure of ECMAScript code.

詞法環境是一種規范類型,在詞法嵌套的 ECMAScript 代碼中,用于定義標識符與特定變量和函數關聯,也就是說JS中的變量和函數存在這個詞法環境中

通常當function聲明,with語句或try..catch語句執行時,都會有一個新的詞法環境被創建

根據ES6的規范,Lexical Environments 主要由兩個部分組成:

A Lexical Environment consists of an Environment Record and a possibly null reference to an outer Lexical Environment.

  • Environment Record(環境記錄項)
  • outer Lexical Environment(外部詞法環境的引用)

1.Environment Record(環境記錄項)

ES6規范中,是這樣定義Environment Record的:

An Environment Record records the identifier bindings that are created within the scope of its associated Lexical Environment. It is referred to as the Lexical Environment’s EnvironmentRecord

一個環境記錄項記錄著,在其關聯的詞法環境內創建的標識符綁定,它被稱為詞法環境的環境記錄

可以將Environment Record(環境記錄項)看成在存儲詞法環境中,與標識符綁定的變量和函數的對象。

從規范角度,Environment Record(環境記錄項)可以視作一個面向對象結構的抽象類,并且擁有三個子類

For specification purposes Environment Record values are values of the Record specification type and can be thought of as existing in a simple object-oriented hierarchy where Environment Record is an abstract class with three concrete subclasses,

此外聲明式環境記錄項中還有function Environment Recordmodule Environment Record兩種類型

  • declarative Environment Record(聲明式環境記錄項)
    • function Environment Record(函數式環境記錄項)
    • module Environment Record(模塊式環境記錄項)
  • object Environment Record(對象式環境記錄項)
  • global Environment Record(全局式環境記錄項)

1.1 declarative Environment Record(聲明式環境記錄項)

Declarative Environment Records are used to define the effect of ECMAScript language syntactic elements such as FunctionDeclarations, VariableDeclarations, and Catch clauses that directly associate identifier bindings with ECMAScript language values.

聲明式環境記錄項用于定義那些將標識符與ECMAScript 語言值綁定的ECMAScript 語法元素,比如 FunctionDeclarations(function 聲明), VariableDeclarations(var 聲明), and Catch clauses(catch 語句)

像日常使用的varletconstfunction聲明的變量,就存放在declarative Environment Record這種詞法環境中,比如如下變量和函數都會放在聲明式環境記錄項中:

//所有元素,包括a,b,c,e都綁定在聲明式環境記錄項中
function foo(a){
    var b = 10;
    function c() {}
}
try {
   ...
} catch(e){}

聲明式環境記錄項又分為function Environment Record(函數式環境記錄項) 和module Environment Record(模塊式環境記錄項)

function Environment Record(函數式環境記錄項)

函數式環境記錄項是聲明式環境記錄項的一種,用于表示函數*作用域。有以下特殊情況需要注意:

  • 除箭頭函數外的其他函數,其環境記錄項都會進行this綁定
  • 非箭頭函數且有super引用的函數,其環境記錄項會包含從函數內部執行super方法調用的狀態

除了聲明式環境記錄項的規范方法外,還有以下字段:

字段名 解釋
[[thisValue]] 任意值 用于此函數調用的this值
[[thisBindingStatus]] "lexical", "initialized", "uninitialized" 如果值為"lexical",說明是箭頭函數,該函數也不會擁有this值
[[FunctionObject]] Object 表示被調用的函數對象,一旦這個函數對象被調用,此環境記錄項就會創建
[[HomeObject]] Object, undefined 如果該函數擁有super屬性值,并且不是箭頭函數。[[HomeObject]]指函數作為方法綁定的對象,默認值為undefined
[[NewTarget]] Object, undefined 如果該環境記錄項是由[[Construct]]內部方法創建的,[[NewTarget]]的值是[[Construct]]newTarget參數的值。默認值為undefined

module Environment Record(模塊式環境記錄項)

A module Environment Record is a declarative Environment Record that is used to represent the outer scope of an ECMAScript Module. In additional to normal mutable and immutable bindings, module Environment Records also provide immutable import bindings which are bindings that provide indirect access to a target binding that exists in another Environment Record.

模塊式環境記錄項也是聲明式環境記錄項的一種,用于表示ECMAScript 模塊的外部范圍。除了正常的可變和不可變綁定之外,模塊環境記錄還提供不可變導入綁定,這些導入綁定提供了對另一個環境記錄中存在的目標綁定的間接訪問。

用自己的話解釋就是,它不僅包括模塊的*聲明外,還包括由模塊顯式導入的綁定。其outer值指向全局環境的詞法環境:

moduleEnvironment = {
    environmentRecord: {
        ...
    }
    //引用全局
    outer: global.LexicalEnvironment
}

1.2 object Environment Record(對象式環境記錄項)

Each object Environment Record is associated with an object called its binding object. An object Environment Record binds the set of string identifier names that directly correspond to the property names of its binding object.

每一個對象式環境記錄項都有一個關聯的對象,這個對象被稱作綁定對象。對象式環境記錄項直接將一系列標識符與其綁定對象的屬性名稱建立一一對應關系。

對象式環境記錄項記錄其綁定對象的屬性名稱以及對應值,比如對于一個對象和對應的對象式環境記錄項:

var obj = {
    name: "obj",
    number: 1
}

假設其在瀏覽器環境下,則其偽代碼如下:

obj.lexicalEnvironment = {
    environmentRecord: { name: "obj", number: 1},
    outer: window.lexicalEnvironment
}

此外,對象是環境記錄項用在with聲明語句中,每當with語句執行時,都會創建一個帶有對象環境記錄的新詞法環境,比如下面的代碼:

var a = 10;
var b = 20;
with ({a: 30}) {
    //這里創建了一個新詞法環境,
    //內部的環境項和with內部聲明的對象一一綁定
    console.log(a + b);//50
}
console.log(a + b);//30

假設其在瀏覽器全局作用域下,那么其偽代碼如下:

//全局環境下詞法環境,初始狀態
window.lexicalEnvironment = {
  environmentRecord: {a: 10, b: 20},
  outer: null
};
//當執行到with語句時
//1.暫存當前詞法環境
previousEnvironment = window.lexicalEnvironment;
//2.創建一個新的詞法環境
withEnvironment = {
    environmentRecord: {a:30},
    outer: window.lexicalEnvironment
};
//3.替代當前詞法環境
window.lexicalEnvironment = withEnvironemt;
//with語句執行完后,復原詞法環境
context.lexicalEnvironment = previousEnvironment;

1.3 global Environment Record(全局式環境記錄項)

A global Environment Record is used to represent the outer most scope that is shared by all of the ECMAScript Script elements that are processed in a common Realm (8.2). A global Environment Record provides the bindings for built-in globals (clause 18), properties of the global object, and for all top-level declarations (13.2.8, 13.2.10) that occur within a Script.

全局環境記錄用于表示在共同領域中處理的所有ECMAScript腳本元素共享的最外部作用域。全局環境記錄為內置全局變量,全局對象的屬性以及腳本中發生的所有*聲明提供了綁定。

用偽代碼可以表示為:

globalEnvironment = {
    environmentRecord: {
        type: "global",
    },
    outer: null
}

邏輯上全局式環境記錄項只有一個,當它實際上是對象式環境記錄項和聲明式環境記錄項的復合對象。全局式環境記錄項基于領域中的全局對象,此外包含所有內置全局變量的綁定,FunctionDeclaration引入的所有綁定,以及GeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableStatement全局代碼。

全局環境記錄項中有這些字段

字段名 解釋
[[ObjectRecord]] Object Environment Record 綁定對象是global object。 它包含全局內置綁定以及FunctionDeclaration, GeneratorDeclaration, 和 VariableDeclaration在全局代碼中綁定相關聯的領域(realm).
[[DeclarativeRecord]] Declarative Environment Record 包含除了FunctionDeclarationGeneratorDeclarationVariableDeclaration綁定之外的關聯作用域代碼的全局代碼中的所有聲明的綁定.
[[VarNames]] List of String 由相關領域的全局代碼中的FunctionDeclarationGeneratorDeclarationVariableDeclaration聲明綁定的字符串名稱。

2.outer Lexical Environment(外部詞法環境的引用)

The outer environment reference is used to model the logical nesting of Lexical Environment values. The outer reference of a (inner) Lexical Environment is a reference to the Lexical Environment that logically surrounds the inner Lexical Environment.

外部詞法環境引用用于表示詞法環境的邏輯嵌套關系模型。(內部)詞法環境的外部引用是邏輯上包含內部詞法環境的詞法環境。

outer是指向外部詞法環境的引用,它在不同環境下,其值會隨之不同:

  • 全局環境下,沒有詞法環境對其進行包圍,所以其詞法環境的outernull
  • 模塊環境下,全局環境將其包圍,因此其outer 指向全局環境的詞法環境
  • 函數環境下,其外部詞法環境是該函數聲明時包圍其的詞法環境,比如:
//聲明a時,處于全局環境下,因此a詞法環境的outer指向全局環境的詞法環境
function a(){ //a:lexicalEnvironment.outer = global.lexicalEnvironment
    console.log(name);
}
function b(){ //b:lexicalEnvironment.outer = global.lexicalEnvironment
    var name = "b";
    a();//global
}
var name = "global";
b();//global

如果將函數的聲明放在嵌套函數詞法環境內部:

function b(){ //b:lexicalEnvironment.outer = global.lexicalEnvironment
    var name = "b";
    //聲明a時,處于b的詞法環境下,因此a詞法環境的outer指向b的詞法環境
    function a(){ //a:lexicalEnvironment.outer = b.lexicalEnvironment
   	   console.log(name);
	}
    a();//b
}
var name = "global";
b();//b

發現沒,如果把嵌套的不同詞法環境的outer值連接在一起,就形成了一條作用域鏈。

舉個例子,在瀏覽器環境下的多個嵌套函數,其作用域鏈為: foo3->foo2->foo1->windows

//作用域鏈 foo3->foo2->foo1->windows
function foo1() {
//...
  function foo2() {
  //...
    function foo3() {
    //...
  }
 }  
}

介紹完詞法環境,下面就進入正題,具體來看看執行上下文的結構:

三.執行上下文的結構

Execution context has state components
執行上下文擁有以下組件

組件 Purpose
code evaluation state Any state needed to perform, suspend, and resume evaluation of the code associated with this execution context. 記錄執行上下文代碼執行、掛起和恢復等狀態
Function If this execution context is evaluating the code of a function object, then the value of this component is that function object. If the context is evaluating the code of a Script or Module, the value is null. 如果當前執行上下文正在執行的是函數對象的代碼,Function 值指向正在執行的函數對象,如果是執行的是腳本和模塊,該值為 null。正在運行的執行上下文的 Function 值也稱為活動函數對象
Realm The Realm from which associated code accesses ECMAScript resources. 關聯代碼訪問ECMAScript資源,指代當前上下文所屬領域的資源,包括全局對象、與此領域相關的代碼使用的內在值等等,用于隔離其他領域
LexicalEnvironment Identifies the Lexical Environment used to resolve identifier references made by code within this execution context. 標識符,標識用于解析此執行上下文中引用的詞法環境,letconst聲明的變量會掛載到該標識符引用的詞法環境中
VariableEnvironment Identifies the Lexical Environment whose EnvironmentRecord holds bindings created by VariableStatements within this execution context. 標識符,標識詞法環境,其綁定由 var 聲明的EnvironmentRecord,也就是var聲明的變量會存儲在此環境中
Generator The GeneratorObject that this execution context is evaluating. 記錄當前正在解析的執行器對象

用偽代碼表示:

ExecutionContext = {
    codeEvaluationState,
    Function,
    Realm,
    LexicalEnviroment: {...},
    VariableEnvironment: {...},
    Generator: {...},
}

1. code evaluation state

At some later time a suspended execution context may again become the running execution context and continue evaluating its code at the point where it had previously been suspended. Transition of the running execution context status among execution contexts usually occurs in stack-like last-in/first-out manner.

code evaluation state 是記錄當前上下文在上下文執行棧中的狀態,用于切換棧中的不同執行上下文,主要有:

  • perform(執行)
  • suspend(掛起)
  • resume(恢復)

2. Function

Function 值是記錄當前執行上下文是否為函數執行上下文:

  • 若當前是全局或函數執行上下文,其值為全局或函數
  • 若當前是腳本_Script_或模塊_Module_ ,其值為null

3. Realm

Before it is evaluated, all ECMAScript code must be associated with a Realm. Conceptually, a realm consists of a set of intrinsic objects, an ECMAScript global environment, all of the ECMAScript code that is loaded within the scope of that global environment, and other associated state and resources.

根據ES6的定義,所有ECMAScript 代碼都有一個與之關聯的Realm領域。一個realm由一系列內置對象,一個ECMAScript全局環境,加載到全局環境中的ECMAScript代碼以及其他關聯狀態和資源組成。

RealmRealm Record的形式來表示,一個Realm Record主要由以下字段組成:

字段名 解釋
[[intrinsics]] Objects 當前Realm中的內部固有對象,比如ObjectFunction,Boolean
[[globalThis]] Object 當前Realm中的全局對象
[[globalEnv]] Lexical Environment 當前Realm中的詞法環境
[[templateMap]] A List of Record 當前Realm中的模版(比如字符串模版)的存儲信息,比如JavaScript具體實現中,是用來存儲模板字符串(template string)的緩存。下次再找模版會優先從此處查詢

RealmECMAScipt規范定義的一個概念,和上節提到的作用域概念有些重合。事實上Realm包含了作用域概念,除了作用域的變量和函數,它還加上了內置對象,比如ObjectFunction,Boolean等,以及加載到全局環境中的其他代碼等。

實際上在瀏覽器環境中,window是就是一個Realm, node中的global也是一個Realm,對比我們平常熟知的作用域概念,Realm更符合JS代碼實際執行中需要的“執行環境”。

4. LexicalEnvironment

Identifies the Lexical Environment used to resolve identifier references made by code within this execution context.

標識用于解析在此執行上下文中由代碼創建的標識符引用的詞法環境。一般是let, const 聲明的變量存儲在該詞法環境中

這里要和Lexical Environment 詞法環境(中間有空格)區分一下:

  • LexicalEnvironment 是執行上下文中的一個標識符,引用的是存儲let, const 聲明變量的詞法環境
  • Lexical Environment 是ES6規范定義的一個概念,包括 Environment Record 和 outer 引用兩個部分

5. ?VariableEnvironment

Identifies the Lexical Environment whose EnvironmentRecord holds bindings created by VariableStatements within this execution context.

標識執行上下文中的詞法環境,其詞法環境是在var聲明創建綁定的詞法環境,也就是這個詞法環境存儲的是var聲明的變量

無論是LexicalEnvironment 還是LexicalEnvironment ,在執行上下文中都是詞法環境。在執行上下文創建時,其內部的LexicalEnvironmentLexicalEnvironment 值相等。

除了這些字段,執行上下文中還有一些抽象方法。下面根據上下文中的抽象方法,來看看執行上下文中的this值是怎樣變化的:

6. 執行上下文中的this

執行上下文中主要通過GetThisEnvironment ( )來確定,來看看ES6規范里面是怎么說的:

The abstract operation GetThisEnvironment finds the Environment Record that currently supplies the binding of the keyword this.

抽象操作 GetThisEnvironment 查找當前提供關鍵字this綁定的環境記錄

執行上下文在實際執行中,通過調用GetThisEnvironment ( )來獲取其this綁定值。其具體執行步驟如下

GetThisEnvironment performs the following steps:

  1. Let lex be the running execution context’s LexicalEnvironment.
  2. Repeat
    a. Let envRec be lex’s EnvironmentRecord.
    b. Let exists be envRec.HasThisBinding().
    c. If exists is true, return envRec.
    d. Let outer be the value of lex’s outer environment reference.
    e. Let lex be outer.

獲取當前執行上下文的this值可以用如下偽代碼表示:

function GetThisEnvironment(){
    var lex = currentLexicalEnvironment;
    while(true){
	    var envRec = lex.EnvironmentRecord;
	    if(envRec.HasThisBinding()){
	        return envRec;
	    }
	    lex = envRec.outer;
    }
}
//返回一個提供this綁定的環境記錄項
var envRec = GetThisEnvironment();
//通過環境記錄項內部抽象方法獲取this值
envRec.GetThisBinding();

四、 執行上下文棧 ( Call Execution stack )

先來看ES6規范中是如何定義執行上下文棧的:

At any point in time, there is at most one execution context that is actually executing code. This is known as the running execution context. A stack is used to track execution contexts. The running execution context is always the top element of this stack.

A new execution context is created whenever control is transferred from the executable code associated with the currently running execution context to executable code that is not associated with that execution context. The newly created execution context is pushed onto the stack and becomes the running execution context.

在任意(代碼執行)的時間點中,最多有一個執行上下文在實際執行代碼。這稱為運行執行上下文。堆棧用于跟蹤執行上下文。正在運行的執行上下文始終是該堆棧的頂部元素。

每當控制從與當前運行的執行上下文關聯的可執行代碼轉移到不與該執行上下文關聯的可執行代碼時,就會創建一個新的執行上下文。新創建的執行上下文被壓入堆棧并成為正在運行的執行上下文。

從ES6規范我們知道:

  • 執行上下文棧是用來跟蹤執行上下文的,當前處于棧頂的是正在運行的執行上下文
  • 調用其他關聯的可執行代碼時,會創建一個新的執行上下文,并將這個新的執行上下文壓入棧頂

借助一個例子來說明:

function a() {
    console.log("function a");
}

function b() {
    console.log("function b");
    a();
}
//執行b()
b();

在 chrome devtools 中debugger看執行上下文棧的執行情況:

第一步:在執行b()前會創建一個全局執行上下文,就是下圖中的(anonymous)

第二步:將b()函數執行上下文壓入棧中:

第三步:當b()調用a()時,將a()函數執行上下文繼續壓入棧:

第四步:執行完a()后,將a()函數執行上下文出棧:

第五步:執行完b()后,將b()函數執行上下文出棧,最后只留下全局執行上下文

五、從 ECMAScript6 角度看代碼的執行流程

代碼的執行主要分為兩個階段:

  • 編譯階段
  • 執行階段

下面以這一段代碼,用 ECMAScript 6 規范解讀代碼的執行流程。

var a = 10;
let b = 20;
const c = 30;
function add(d, e) {
    var f = 40;
    return d + e + f;
}
foo(50, 60);

在開始前,先回顧一下ES6規范中的執行上下文,用偽代碼表示:

ExecutionContext = {
    codeEvaluationState, //記錄當前上下文在上下文執行棧中的狀態
    Function, //當前執行上下文在執行中是否有函數對象,有的話Function值就指向這個函數對象
    Realm, //當前執行上下文的領域/作用域
    LexicalEnviroment: {...}, //let,const等變量聲明存儲在此類詞法環境
    VariableEnvironment: {...},//var變量聲明存儲在此類詞法環境
    Generator: {...},//當前執行上下文在執行中是否有生成器函數,有的話Generator值就指向這個生成器函數
}

在日常代碼分析中,在執行上下文中,對codeEvaluationStateFunctionRealmGenerator 關注的較少,我們著重分析LexicalEnviromentVariableEnvironment和其記錄項中的this綁定值。下面就開始分析吧:

1.編譯階段

在這個階段,JS引擎會掃描變量和函數聲明,創建一個全局上下文,做好執行之前的代碼編譯和初始化工作,用偽代碼表示:

//全局上下文
GlobalExectionContext = {
   //詞法環境
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // let和const變量聲明不會提升
      b: < uninitialized >,
      c: < uninitialized >,
      // add 進行函數提升
      add: < func >,
      //記錄項的this值綁定到全局對象
      ThisBinding: <Global Object>,
    }
    outerEnv: <null>,
    
  },
  //變量環境
  VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // var變量聲明會進行提升
      a: undefined,
      ThisBinding: <Global Object>
    }
    outerEnv: <null>,
  }
}

上述的執行上下文對應代碼范圍如下:

var a = 10;
let b = 20;
const c = 30;
function add(d, e) {
    var f = 40;
    return d + e + f;
}

add(d,e)函數被調用時,會創建一個函數執行上下文,并將這個上下文壓入調用棧中,用偽代碼表示add(d, e)函數執行上下文:

//add(d, e)函數執行上下文
FunctionExectionContext = {
    LexicalEnvironment: {
        EnvironmentRecord: {
          Type: "Declarative",
          // Arguments標識符綁定,并將實參傳入其中
          Arguments: {0: 50, 1: 60, length: 2},
          ThisBinding: <Global Object or undefined>,
        },
        outerEnv: <GlobalLexicalEnvironment>,
      },
    VariableEnvironment: {
        EnvironmentRecord: {
          Type: "Declarative",
          //var聲明變量提升 
          d: undefined,
          ThisBinding: <Global Object or undefined>
        },
        outerEnv: <GlobalLexicalEnvironment>,
      }
}

2.執行階段

執行階段主要是這一段代碼的執行:

foo(50, 60);

此時全局執行上下文的變化為:

  • letconst 聲明的變量得到賦值:b 賦為 20,c賦為30
  • var聲明的變量 a 由 undefined覆蓋為 10
//全局上下文
GlobalExectionContext = {
   //詞法環境
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // let和const聲明的變量得到賦值
      b: 20,
      c: 30,
      add: < func >,
      //記錄項的this值指向到全局對象
      ThisBinding: <Global Object>,
    }
    outerEnv: <null>,
    
  },
  //變量環境
  VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // var變量聲明會進行提升
      a: 10,
      ThisBinding: <Global Object>
    }
    outerEnv: <null>,
  }
}

函數執行上下文的變化為:

  • var聲明的變量 f 由 undefined覆蓋為 40
  • add(d, e) 函數執行上下文在執行完畢后,會返回計算結果值 150
//add(d, e)函數執行上下文
FunctionExectionContext = {
    LexicalEnvironment: {
        EnvironmentRecord: {
          Type: "Declarative",
          // Arguments標識符綁定,并將實參傳入其中
          Arguments: {0: 50, 1: 60, length: 2},
          ThisBinding: <Global Object or undefined>,
        },
        outerEnv: <GlobalLexicalEnvironment>,
      },
    VariableEnvironment: {
        EnvironmentRecord: {
          Type: "Declarative",
          d: 40,
        },
        ThisBinding: <Global Object or undefined>,
        outerEnv: <GlobalLexicalEnvironment>,
      }
}

在函數執行完畢后,該add(d,e)函數執行上下文會出棧,該函數執行上下文內的變量也隨之銷毀。

參考文章

http://dmitrysoshnikov.com/ecmascript/es5-chapter-3-2-lexical-environments-ecmascript-implementation/#declarative-environment-record

https://www.linkedin.com/pulse/javascript-under-hood-part-2-simple-example-execution-kabir

https://blog.openreplay.com/explaining-javascript-s-execution-context-and-stack/

https://blog.openreplay.com/explaining-javascript-s-execution-context-and-stack/

總結

以上是生活随笔為你收集整理的从 ECMAScript 6 角度谈谈执行上下文的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。