大家好,我是归思君

起因是最近了解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 角度谈谈执行上下文的更多相关文章

  1. JavaScript内部原理系列-执行上下文(Execution Context)

    概要 本文将向大家介绍ECMAScript的执行上下文以及相关的可执行代码类型. 定义 每当控制器到达ECMAScript可执行代码的时候,控制器就进入了一个执行上下文.执行上下文(简称:EC)是个抽 ...

  2. 从执行上下文角度重新理解.NET(Core)的多线程编程[1]:基于调用链的”参数”传递

    线程是操作系统能够进行运算调度的最小单位,操作系统线程进一步被封装成托管的Thread对象,手工创建并管理Thread对象已经成为了所能做到的对线程最细粒度的控制了.后来我们有了ThreadPool, ...

  3. 从执行上下文角度重新理解.NET(Core)的多线程编程[2]:同步上下文

    一般情况下,我们可以将某项操作分发给任意线程来执行,但有的操作确实对于执行的线程是有要求的,最为典型的场景就是:GUI针对UI元素的操作必须在UI主线程中执行.将指定的操作分发给指定线程进行执行的需求 ...

  4. 从执行上下文(ES3,ES5)的角度来理解"闭包"

    目录 介绍执行上下文和执行上下文栈概念 执行上下文 执行上下文栈 伪代码模拟分析以下代码中执行上下文栈的行为 代码模拟实现栈的执行过程 通过ES3提出的老概念-理解执行上下文 1.变量对象和活动对象 ...

  5. javascript系列之执行上下文

    原文:javascript系列之执行上下文 写在前面:一 直想系统的总结一下学过的javascript知识,喜欢这门语言也热爱这门语言.未来想从事前端方面的工作,提前把自己的知识梳理一下.前面写了些 ...

  6. 深入理解JavaScript系列(11):执行上下文(Execution Contexts)

    简介 从本章开始,我将陆续(翻译.转载.整理)http://dmitrysoshnikov.com/网站关于ECMAScript标标准理解的好文. 本章我们要讲解的是ECMAScript标准里的执行上 ...

  7. 解读闭包,这次从ECMAScript词法环境,执行上下文说起

    对于x年经验的前端仔来说,项目也做了好些个了,各个场景也接触过一些.但是假设真的要跟面试官敞开来撕原理,还是有点慌的.看到很多大神都在手撕各种框架原理还是有点羡慕他们的技术实力,羡慕不如行动,先踏踏实 ...

  8. 从个人的角度谈谈本次GNTC大会的收获

    GNTC资料:from sdnlab 从个人的角度谈谈本次大会的收获 从本次大会的主题演讲来看,目前SDN.NFV的最前沿已经不再像五年前持观望态度以及探讨,各大运营商.各大厂商已经将SDN.NFV具 ...

  9. Execution Contexts (执行上下文)

    本章我们一起讨论一下ECMAScript的执行上下文及相关可执行代码的各种类型.so...什么是执行上下文?我们来看看定义: 每次当控制器转到ECMAScript可执行代码的时候, 即会进入到一个执行 ...

  10. JavaScript 执行环境(执行上下文) 变量对象 作用域链 上下文 块级作用域 私有变量和特权方法

    总结自<高程三>第四章  理解Javascript_12_执行模型浅析   JS的执行环境与作用域  javascript高级程序第三版学习笔记[执行环境.作用域] 在javascript ...

随机推荐

  1. sublime运行php文件

    sublime 运行 php 文件 使用 sublime 打开一个php文件 然后 Tools -> Build System -> New Build System 将以上打开的文件内容 ...

  2. 月工资不到10元的内容审核专员? - ChatGPT 在内容自动审查中的应用

    内容过滤筛查是指对网络上发布或传播的文本.图片.视频等内容进行审核和监管,以防止出现违法违规.暴力色情.虚假广告.电信诈骗等现象,维护网络安全和社会秩序. 内容过滤筛查是一个亟待解决的问题,因为网络内 ...

  3. 循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(3)--自定义用户控件

    在我们创建界面元素的时候,不管在Vue3+ElementPlus的前端上,还是Winform桌面端上,都是会利用自定义用户控件来快速重用一些自定义的界面内容,对自定义用户控件的封装处理,也是我们开发W ...

  4. (数据科学学习手札154)geopandas 0.14版本新特性一览

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,就在前两天,Python生态中 ...

  5. Mysql中文字符串提取datetime

    DATE_FORMAT无法用于提取含中文字符的时间字符串中的时间, 可以通过STR_TO_DATE来提取其中的信息, 如下: SELECT STR_TO_DATE("2018年11月05日 ...

  6. 文心一言 VS 讯飞星火 VS chatgpt (95)-- 算法导论9.2 4题

    四.用go语言,假设用RANDOMIZED-SELECT 去选择数组 A=(3,2,9,0,7,5,4,8,6,1)的最小元素,给出能够导致 RANDOMIZED-SELECT最坏情况发生的一个划分序 ...

  7. Solution Set -「CF 1514」

    「CF 1514A」Perfectly Imperfect Array Link. 就看序列中是否存在不为平方数的元素即可. #include<bits/stdc++.h> using n ...

  8. Vue 搭配 Spring MVC 创建一个 web 项目

    Vue 搭配 Spring MVC 创建一个 web 项目 想要写一个登录的web应用程序.页面使用Vue,后端使用Spring MVC,最终打成war包,放在tomcat下启动. 1.创建Sprin ...

  9. python第6章code

    01条件判断语句 # 条件判断语句(if语句)# 语法:if 条件表达式 : # 代码块# 执行的流程:if语句在执行时,会先对条件表达式进行求值判断,# 如果为True,则执行if后的语句# 如果为 ...

  10. android 中ids.xml资源的使用

    ids.xml 前面我们见识过ids.xml文件,但是这个文件是什么意思呢?我们来看下文档中的介绍: 先看下它给的例子: XML file saved at res/values/ids.xml: 使 ...