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

news2024/9/20 18:25:44

大家好,我是归思君

起因是最近了解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(全局式环境记录项)

环境记录项.png

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 stateAny state needed to perform, suspend, and resume evaluation of the code associated with this execution context. 记录执行上下文代码执行、挂起和恢复等状态
FunctionIf 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 值也称为活动函数对象
RealmThe Realm from which associated code accesses ECMAScript resources. 关联代码访问ECMAScript资源,指代当前上下文所属领域的资源,包括全局对象、与此领域相关的代码使用的内在值等等,用于隔离其他领域
LexicalEnvironmentIdentifies the Lexical Environment used to resolve identifier references made by code within this execution context. 标识符,标识用于解析此执行上下文中引用的词法环境,letconst声明的变量会挂载到该标识符引用的词法环境中
VariableEnvironmentIdentifies the Lexical Environment whose EnvironmentRecord holds bindings created by VariableStatements within this execution context. 标识符,标识词法环境,其绑定由 var 声明的EnvironmentRecord,也就是var声明的变量会存储在此环境中
GeneratorThe 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(恢复)

codeEvaluationStatus.png

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 {[[strings]]: List, [[array]]: Object}当前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)
image-1.png

第二步:将b()函数执行上下文压入栈中:
image-2.png

第三步:当b()调用a()时,将a()函数执行上下文继续压入栈:
image-3.png

第四步:执行完a()后,将a()函数执行上下文出栈:
image-4.png

第五步:执行完b()后,将b()函数执行上下文出栈,最后只留下全局执行上下文
image-5.png

image-6.png

五、从 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/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1325891.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux 驱动——私有数据

文章目录 linux 驱动中的私有数据container_of驱动程序数据结构定义 应用程序模块使用 linux 驱动中的私有数据 前面的程序中&#xff0c;都只申请了一个从设备号&#xff0c;这里使用 alloc_chrdev_region 分配两个设备号&#xff0c;这两个设备共用 ops 方法。 所以需要在 …

获投1050万欧元!德国量子公司Kipu Quantum成功研发特定压缩算法

​&#xff08;图片来源&#xff1a;网络&#xff09; 近日&#xff0c;德国量子软件公司Kipu Quantum宣布成功完成种子轮融资&#xff0c;融资总额达1050万欧元&#xff08;约合8000万人民币&#xff09;。该初创公司目前已开发出运行高性能量子计算机所需的压缩算法。该算法…

MyBatis-Flex 尝鲜

MyBatis-Flex 官网&#xff1a;官网地址 快速上手&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xmlns"http://maven.apache.org/POM/4.0.0"xsi:…

如何让公司高层理解和支持IPD?从这几个方面进行培训和研讨

前几天&#xff0c;华研荟介绍了基于BLM模型的战略规划研讨会如何开&#xff0c;详细说明了每一个步骤的主要活动、相关表单和注意事项。感兴趣的话可以看我主页的历史文章。 在规划战略的时候&#xff0c;新产品开发一定是一项重要战略之一&#xff0c;那么如何提高开发的效率…

DTC营销新模式,创新商业引领裂变营销新潮流的玩法!

DTC营销新模式&#xff0c;创新商业引领裂变营销新潮流的玩法&#xff01; 随着市场竞争的加剧&#xff0c;企业寻求创新的营销模式以突破困境&#xff0c;脱颖而出。其中&#xff0c;DTC&#xff08;Direct-to-Consumer&#xff0c;直接面向消费者&#xff09;营销新模式应运…

Android应用-Flutter实现丝滑的滑动删除、移动排序等-Dismissible控件详解

文章目录 Dismissible 简介使用场景常用属性基本用法举例注意事项 Dismissible 简介 Dismissible 是 Flutter 中用于实现可滑动删除或拖拽操作的一个有用的小部件。主要用于在用户对列表项或任何其他可滑动的元素执行删除或拖动操作时&#xff0c;提供一种简便的实现方式。 使…

leetcode 974. 和可被 K 整除的子数组(优质解法)

代码&#xff1a; class Solution {public int subarraysDivByK(int[] nums, int k) {HashMap<Integer,Integer> hashMapnew HashMap();hashMap.put(0,1);int count0; //记录子数组的个数int last0; //前一个下标的前缀和int now0; //当前下标的前缀和for(int i0;…

fill-in-the-middle(FIM) 实现与简单应用

1 背景 传统训练的 GPT 模型只能根据前文内容预测后文内容&#xff0c;但有些应用比如代码生成器&#xff0c;需要我们给出上文和下文&#xff0c;使模型可以预测中间的内容&#xff0c;传统训练的 GPT 就不能完成这类任务。 传统训练的 GPT 只能根据上文预测下文 使用 FIM…

Linux开发工具——vim篇

vim开发工具的使用 文章目录 vim开发工具的使用认识vimvim常用三种模式vim正常模式命令集模式切换移动光标删除文字赋值替换撤销上一次操作更改跳到指定的行 vim末行模式命令集列出行号跳到文件中的某一行&#xff1a;保存文件离开vim查找字符&#xff1a; 总结题外话&#xff…

EasyRecovery易恢复软件2024个人版安装下载教程

EasyRecovery是一款操作安全、价格便宜、用户自主操作的非破坏性的只读应用程序&#xff0c;它不会往源驱上写任何东西&#xff0c;也不会对源驱做任何改变。它支持从各种各样的存储介质恢复删除或者丢失的文件&#xff0c;其支持的媒体介质包括&#xff1a;硬盘驱动器、光驱、…

项目从0到1,架构选型 :单体架构优先考虑

当我听到关于团队使用微服务架构的故事时&#xff0c;我注意到了一个共同的现象。 几乎所有成功的微服务故事都是从一个过于庞大的庞然大物开始的&#xff0c;后来这个庞然大物被拆分了我所听说的几乎所有从零开始构建微服务系统的案例&#xff0c;最终都陷入了严重的麻烦。 …

DRF从入门到精通二(Request源码分析、DRF之序列化组件)

文章目录 一、Request对象源码分析区分原生request和新生request新的request还能像原来的reqeust一样使用吗源码片段分析总结&#xff1a; 二、DRF之序列化组件序列化介绍序列化步骤序列化组件的基本使用反序列化基本使用反序列化的新增反序列化的新增删除单条 反序列化的校验 …

大文件传输之传输协议TCP和UDP之间的区别

传输协议是一种规定数据包格式、顺序、重传、确认等细节的约定&#xff0c;确保在不同设备之间正确传送和接收数据。目前常见的协议主要有两种&#xff0c;一是TCP&#xff0c;另一是UDP&#xff0c;它们各自有优势和劣势。下面我们来深入了解。 TCP和UDP的特点和区别&#xff…

力扣题目学习笔记(OC + Swift)17. 电话号码的字母组合

17. 电话号码的字母组合 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 关键字&#xff1a;所有组合 模式识别&#xff1a…

递归算法:二叉树前序、中序、后序遍历解析与递归思想深度剖析

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《linux深造日志》 《高效算法》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 一、二叉树的遍历1.1 链式结构二叉树的创建1.1 二叉树结构图 二、 前序遍历代码演示&#xff1a;2.1 前序遍历递…

李飞飞吴恩达等 2024 年 AI 十大预测!GPU算力短缺,AI 智能体一年内大爆发?

2023 这个大模型爆发的元年即将过去&#xff0c;展望未来&#xff0c;比尔盖茨&#xff0c;李飞飞&#xff0c;吴恩达等人对 2024 年人工智能的发展作出了自己的预测。 2023&#xff0c;可以说是人工智能的春天。 在过去的一年里&#xff0c;ChatGPT 成为家喻户晓的名字&#…

InstructPix2Pix:通过用户指令编辑图像

Brooks T, Holynski A, Efros A A. Instructpix2pix: Learning to follow image editing instructions[C]//Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2023: 18392-18402. InstructPix2Pix 所做的任务是根据用户指令编辑图像。Inst…

SSM整合实战(Spring、SpringMVC、MyBatis)

五、SSM整合实战 目录 一、SSM整合理解 1. 什么是SSM整合&#xff1f;2. SSM整合核心理解五连问&#xff01; 2.1 SSM整合涉及几个IoC容器&#xff1f;2.2 每个IoC容器盛放哪些组件&#xff1f;2.3 IoC容器之间是什么关系&#xff1f;2.4 需要几个配置文件和对应IoC容器关系&…

Ubuntu系统的基础操作和使用

文章目录 系统安装系统界面文件系统包管理命令行常见问题 Ubuntu是一个基于Debian的Linux发行版&#xff0c;以桌面应用为主。它是自由软件&#xff0c;意味着你可以自由地使用、复制、研究、修改和改进这个软件。下面我们将详细介绍Ubuntu系统的基础操作和使用。 系统安装 U…

Android Studio开发之路(六)(合集)界面优化以及启动图标等

一、导航栏背景、字体修改 导航栏、状态栏等背景颜色的修改一般是在themes.xml文件中修改&#xff0c;android一个activity各个部件参考&#xff1a; colorPrimary,colorPrimaryDark等的意义 添加链接描述 但是问题在于&#xff1a;只在这里修改背景颜色的话&#xff0c;可能…