原文:https://blog.bitsrc.io/understanding-execution-context-and-execution-stack-in-javascript-1c9ea8642dd0
执行上下文也叫执行环境?为什么呢就让我这个英语zz来解释下
context:环境; 上下文
执行环境中定义了变量或函数有权访问的其他数据,决定了他们给各自行为,每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保持在这个对象中,虽然我们无法访问到这个对象,但是解析器可以在处理数据的时候在后台使用他
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 代码执行前,执行上下文将经历创建阶段。在创建阶段会发生三件事:
ExecutionContext = {
ThisBinding = ,
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: , // this
outer: // 外部环境引用
},
// 变量环境
VariableEnvironment: {
EnvironmentRecord: {
Type: "Object",
// 在这里绑定标识符
c: undefined,
}
outer: // 外部环境引用
}
}
// 函数
FunctionExectionContext = {
// 词法环境
LexicalEnvironment: {
EnvironmentRecord: {
Type: "Declarative",
// 在这里绑定标识符
Arguments: {0: 20, 1: 30, length: 2}, // 函数的专属 arguments
},
ThisBinding: , // this
outer: // 外部环境引用
},
// 变量环境
VariableEnvironment: {
EnvironmentRecord: {
Type: "Declarative",
// 在这里绑定标识符
g: undefined
},
outer: // 外部环境引用
}
}
原作者更新了部分内容,将this bindng归入词法环境中了,