执行上下文
执行上下文以下简称(上下文)。
什么是上下文
即变量和函数的上下文决定了它们可以访问哪些数据,以及它们的行为。
上下文的组成
const ExecutionContextObj = {
VariableObject: window, // 变量对象
ScopeChain: {}, // 作用域链
this: window,
};
- this:执行上下文中
this的指向,根据调用方式不同而不同。 - 变量对象: 用于存储变量和
函数声明,包括函数参数和内部变量。 - 作用域链: 确保可以访问到的变量的顺序,即当前
上下文的变量对象和外部上下文的变量对象。
上下文的类型
上下文的类型分为三种:
- 全局上下文:
- 在浏览器中,
全局上下文就是window对象。 - 所有通过
var定义的全局变量和函数, 都会成为window对象属性方法。 - 使用
let和const创建的顶级声明则不会定义在全局上下文中。 - 在应用程序退出前才会被销毁,(比如关闭网页,或者退出浏览器)
- 在浏览器中,
- 函数上下文:
- 当函数被调用时创建,会为该函数创建一个新的
上下文。 - 每一个函数都会有自己的上下文。
- 当函数被调用时创建,会为该函数创建一个新的
- eval 上下文
- 指的是运行在
eval函数中的代码,很少用而且不建议使用
- 指的是运行在
执行栈
执行栈,也叫调用栈,被用来存储代码运行时创建的所有上下文。
info
栈:一种数据结构,遵循后进先出的原则
function fn1() {
console.log("fn1被调用了 -- 创建了fn1的函数执行上下文,压入栈");
fn2();
console.log("fn2执行完成,fn2的执行上下文会从栈中弹出");
}
function fn2() {
console.log("fn2被调用了 -- 创建了fn2的函数执行上下文,压入栈");
}
fn1();
console.log("fn1执行完成,fn2的执行上下文会从栈中弹出");

运行结果:
fn1被调用了 -- 创建了fn1的函数执行上下文,压入栈
fn2被调用了 -- 创建了fn2的函数执行上下文,压入栈
fn2执行完成,fn2的执行上下文会从栈中弹出
fn1执行完成,fn2的执行上下文会从栈中弹出
上述代码的执行上下文栈:
- 当上述代码在浏览器加载时,
JavaScript 引擎创建了一个全局执行上下文并把它压入栈中 - 当函数
fn1()被调用时,JavaScript 引擎为该函数创建了一个函数执行上下文,并把它压入当前执行栈的顶部。 - 当
fn1()函数内部调用fn2()函数时,JavaScript 引擎同样创建了fn2()的函数执行上下文并执行栈的顶部。 - 然后执行完毕
fn2()函数后,fn2()函数会从当前栈(后进先出结构)弹出,并且按程序执行顺序继续执行fn1()函数。 - 当
fn1()函数执行完毕,它的执行上下文从栈弹出,控制流程到达全局执行上下文。 - 一旦所有代码执行完毕,
JavaScript 引擎从当前栈中移除全局执行上下文。