← [ BACK_TO_NOTES ]

DevTools Call Stack vs Scope

比较 DevTools 暂停状态下 Call Stack 与 Scope 的职责:前者解释控制流如何到达当前 frame,后者解释当前执行上下文可访问的值与绑定。

#synthesis #growing #frontend #browser #chrome-devtools

[!info] related notes

DevTools Call Stack vs Scope

一句话关系

Call Stack
→ 控制流从哪里来

Scope
→ 当前 frame 能看到什么值

一个解释路径,一个解释状态。

Call Stack

当执行暂停时,每个 frame 对应一次尚未返回的函数调用/执行上下文。

从当前 frame 向上可以回答:

  • 当前函数是谁调用的;
  • 上一层参数从哪里来;
  • 某事件/请求/回调经过了哪些业务函数;
  • 异常怎样一路冒泡到这里。

切换不同 frame 后,Scope 也会跟着改变。

Scope

Scope 展示选中 frame 在该暂停时刻可访问的绑定,例如:

  • local;
  • closure;
  • script/module;
  • global;
  • this。

它适合回答:

这一刻输入已经错了吗?还是在当前函数里才变错?

两者怎样配合

假设最终请求 body 里的 userId 错了:

暂停在 fetch 前
→ Scope: userId 已经错
→ Call Stack: 上一层谁传进来的
→ 切到 caller frame
→ Scope: caller 中原始值是否正确

这样可以逐层把错误边界向上收缩。

异步边界

同步调用栈会在一次 task 结束后清空。

Promise、timer、event listener 的后续 callback 属于新的执行时机。

DevTools 可能展示 async stack/context 来帮助连接来源,但这不意味着 JavaScript 物理上一直保留同一条同步 stack。

所以调试 async bug 时,还要结合:

  • event loop;
  • Promise chain;
  • task/microtask;
  • Network/initiator。

Scope 不是历史记录

Scope 展示暂停时刻的当前绑定,不会自动告诉你:

  • 这个值之前是什么;
  • 谁在 2 秒前修改了它;
  • 哪次 render 导致变化。

需要通过:

  • 更早的 breakpoint;
  • conditional breakpoint;
  • watchpoint/DOM breakpoint;
  • logging/trace;

把变化过程捕获下来。

学习检查

  1. Call Stack 与 Scope 分别回答什么问题?
  2. 为什么切换 Call Stack frame 后 Scope 会变化?
  3. Scope 中发现值已经错误,下一步为什么通常要看 caller frame?
  4. 为什么 Promise callback 的 async stack 不能被理解成一直存在的同步调用栈?
  5. Scope 为什么不能直接回答“谁之前改了这个变量”?
  6. 给一个三层函数调用,把错误值从当前 frame 追溯到最早污染点。
创建于 2026/4/13 更新于 2026/9/30
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本