← 返回文章列表
JavaScript·80 次阅读

深入 V8:执行上下文、词法环境与调用栈

深入 V8:执行上下文、词法环境与调用栈

想真正理解作用域、闭包、this,需要看代码在 JS 引擎内部是怎么被执行的。以 V8 为例梳理。

执行流程概览

JS 源码
→ Parser 词法/语法分析,生成 AST
→ Ignition 解释器把 AST 编译成字节码
→ 逐行执行字节码,热点函数由 TurboFan 优化为机器码

函数只在调用时才编译内部代码(懒解析),提升启动速度。

执行上下文 Execution Context

每次函数调用都会创建一个执行上下文,包含代码运行所需的全部信息:

  • 变量环境 / 词法环境(Lexical Environment):存放变量、函数声明,以及指向外层环境的引用
  • this 绑定

词法环境的结构:环境记录(当前作用域的变量表)+ 对父环境的引用(outer)。这条引用链在函数定义时就确定了——这就是作用域为词法作用域的原因,也是闭包的实现基础:外层函数执行结束、其执行上下文弹栈后,只要内部函数还持有对该词法环境的引用,环境就不会被 GC。

调用栈 Call Stack

JS 单线程,函数调用形成后进先出的调用栈:

  1. 全局代码先创建全局上下文入栈
  2. 调用函数 → 新上下文压栈执行
  3. 函数返回 → 上下文弹栈

栈是有容量上限的,无限递归会抛出 RangeError(栈溢出)。事件循环中的 setTimeout 回调不立即入栈,而是等时机成熟、调用栈清空后才执行。

创建阶段的"提升"

进入上下文但代码执行前,引擎会先扫描并注册函数和变量声明(var 初始为 undefined,函数声明整体提升)。理解创建/执行两阶段,就理解了提升现象;let/const 也会被注册但处于"暂时性死区",提前访问直接报错。

与 this、闭包的串联

  • 闭包:函数记住的是定义时的词法环境,与在哪调用无关
  • this:不看词法环境,在调用时绑定(箭头函数例外,它根本不创建自己的 this 绑定,沿词法环境向外找)
  • 事件循环里的每个回调都是一次独立的上下文压栈/弹栈

把这些概念串起来,JS 的核心机制就不再是零散知识点,而是同一套执行模型在不同侧面的表现。

看到这里了?如果这篇文章帮到过你

请我喝瓶可乐就好 🥤

收款码

评论0 条

还没有评论,来抢沙发~

发表评论

评论需审核后显示

© 2026 许冬博客 · 专注 JS 技术分享

·RSS 订阅·Powered by Nuxt 4