JS中的执行上下文和执行栈
什么是执行上下文?
执行上下文是评估和执行JS
代码的环境的抽象的抽象概念,JS
代码在运行时就是在执行上下文中运行
执行上下文是JS代码运行的环境
执行上下文的种类
- 全局(默认)执行上下文:创建全局对象
window
,this
指向全局对象。只有一个 - 函数执行上下文: 每当函数被调用时,就会为函数创建一个专属的上下文。可以存在多个
执行栈
执行栈被用来存储代码运行时的创建的执行上下文。
JS
引擎在遇到代码时,会首先创建一个全局的执行上下文,并压入到栈中。在函数调用时,JS
引擎再创建一个函数执行上下文压入栈中。
JS
引擎会执行位于栈顶的函数,运行结束后,执行栈弹出已运行函数的执行上下文 。随后引擎再执行下个变成栈顶的函数
代码演示
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');
创建执行上下文
创建执行环境
- this的绑定
- 词法环境的初始化
- 变量环境的初始化
词法环境伪代码
GlobalExectionContext = { //全局执行上下文
LexicalEnvironment: { // 词法环境
EnvironmentRecord: { // 词法环境的组件 对象环境记录器
Type: "Object",
// 在这里绑定标识符
}
outer: <null> // 词法环境的组件 外部引用
}
}
FunctionExectionContext = { // 函数执行上下文
LexicalEnvironment: { // 词法环境
EnvironmentRecord: { // 词法环境的组件 声明环境记录器
Type: "Declarative",
// 在这里绑定标识符
}
outer: <Global or outer function environment reference> // 词法环境的组件 外部引用
}
}
变量环境:
let a = 20;
const b = 30;
var c;
function multiply(e, f) {
var g = 20;
return e * f * g;
}
c = multiply(20, 30);
GlobalExectionContext = {
ThisBinding: <Global Object>,
LexicalEnvironment: {
EnvironmentRecord: {
Type: "Object",
// 在这里绑定标识符
a: < uninitialized >,
b: < uninitialized >,
multiply: < func >
}
outer: <null>
},
VariableEnvironment: {
EnvironmentRecord: {
Type: "Object",
// 在这里绑定标识符
c: undefined,
}
outer: <null>
}
}
FunctionExectionContext = {
ThisBinding: <Global Object>,
LexicalEnvironment: {
EnvironmentRecord: {
Type: "Declarative",
// 在这里绑定标识符
Arguments: {0: 20, 1: 30, length: 2},
},
outer: <GlobalLexicalEnvironment>
},
VariableEnvironment: {
EnvironmentRecord: {
Type: "Declarative",
// 在这里绑定标识符
g: undefined
},
outer: <GlobalLexicalEnvironment>
}
}
作用域链
在《JavaScript深入之变量对象》中讲到,当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链。
闭包
函数能访问到函数外部的变量,则函数和这个变量形成了一个闭包
function foo(){
var local = 1
function bar(){
local++
return local
}
return bar
}
var func = foo()
func()
foo
就是变量local
和函数的bar
的闭包
闭包目的
隐藏那个能被函数访问到的变量,换句话说,除了能和那个变量形成闭包的函数,其他的方法都不可以访问它。