JavaScript执行上下文有三种类型:全局执行上下文、函数执行上下文和eval执行上下文;其中全局上下文在脚本加载时创建且唯一,函数上下文每次调用动态生成,eval上下文因安全风险基本被弃用。

JavaScript 执行上下文是代码真正“开始干活”前的准备环境,它不是语法结构,而是一个运行时抽象容器——变量在哪声明、函数怎么找、this 指向谁、代码从哪开始执行,全由它决定。
执行上下文有哪几种类型
JS 引擎只在三种场景下创建执行上下文:
-
全局执行上下文:脚本一加载就自动创建,且整个页面生命周期内仅有一个。浏览器中它的 this 指向
window,所有顶层var、function声明都会挂载到这个对象上。 - 函数执行上下文:每次函数被调用时动态生成,哪怕同一个函数被调用十次,也会产生十个独立上下文。每个都拥有自己的参数、局部变量、this 值和作用域链。
-
Eval 执行上下文:仅当使用
eval()执行字符串代码时触发,现代开发中基本禁用——既难调试又存在安全风险,可忽略不计。
执行上下文的两个关键阶段
每个上下文不是一次性建好就完事,而是分两步推进,这直接解释了“变量提升”和“暂时性死区”等行为:
-
创建阶段(进入上下文时):
• 确定 this 值(如普通函数调用中为全局对象);
• 初始化 词法环境(let/const标记为未初始化);
• 构建 变量环境(var设为undefined,函数声明直接赋值);
• 建立作用域链(用于后续变量查找)。 -
执行阶段(逐行运行代码时):
•var被赋予真实值;
•let/const在声明语句处才真正赋值,之前访问会报ReferenceError(这就是 TDZ);
• 函数调用、表达式求值、return等操作在此阶段发生。
执行上下文栈(Call Stack)怎么管理代码执行
JS 是单线程的,靠执行上下文栈来调度任务顺序:
- 页面启动 → 全局上下文入栈(栈底);
- 调用函数
foo()→ 新的函数上下文压入栈顶; - 若
foo内又调用bar()→bar上下文再压栈顶; -
bar执行完毕 → 弹出;foo继续执行 → 完毕后也弹出; - 最终只剩全局上下文,脚本运行结束。
这个“后进先出”的栈结构,就是你看到控制台报错时堆栈信息的来源,也是理解异步回调执行时机的基础。
执行上下文里到底存了什么
每个上下文内部包含三个核心组件:
-
变量环境(VariableEnvironment):专管
var和函数声明,支持变量提升; -
词法环境(LexicalEnvironment):负责
let、const和块级作用域,有 TDZ 保护; - 作用域链(ScopeChain):由当前词法环境 + 外层词法环境引用组成,决定了变量查找路径(比如函数内找不到就往父函数找,最后到全局)。
这些结构共同构成 JS 动态查找变量和绑定 this 的底层依据,不是概念游戏,而是真实参与每一次取值运算。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











