class 不会被完全提升,仅声明提升且处于暂时性死区(TDZ),必须定义在所有使用它的地方之前;应避免提前实例化,延迟到 class 定义后执行,并用 const/let 替代 var 以暴露 TDZ 错误。

直接把 class 定义放到所有使用它的地方之前,是最简单有效的解决方式。JavaScript 中的 class 不会像函数声明那样被“完全提升”,它虽然会被声明提升,但处于暂时性死区(TDZ),在定义语句执行前访问就会报 ReferenceError: Cannot access 'X' before initialization。
明确 class 的声明顺序
class 和 let/const 一样,只做声明提升,不初始化。这意味着:
- 不能在 class 定义语句之前用
new MyClass() - 不能在 class 定义前通过变量赋值、全局对象挂载等方式间接引用它
- 哪怕只是写在同一个文件顶部,也必须确保 class 声明出现在所有依赖它的代码上方
延迟初始化依赖 class 的变量
如果某些变量需要基于 class 实例化(比如 const q = new Queue()),不要在声明时就赋值,而是推迟到 class 定义之后、真正需要时再创建:
- 把实例化逻辑移到函数内部(如
init()或事件回调中) - 或先用
let q声明,后面再q = new Queue() - 避免在模块顶层、DOM 获取后立即调用
new,尤其当 class 定义在下方时
检查 DOM 和异步操作的执行时机
常见翻车点是:先获取 DOM 元素或建立 WebSocket,再在回调里用 class,但 class 定义还在后面。要确保:
-
document.getElementById等同步操作没问题,但后续的new必须等 class 已定义 - WebSocket 的
onmessage或事件监听器里若用到 class,需确认该 class 在监听器注册前已定义 - 模块加载顺序也要留意,ESM 模块不会自动等待其他模块中的 class 初始化完成
用 const/let 替代 var 来暴露问题
var 声明的变量虽会提升并初始化为 undefined,容易掩盖逻辑错误;而 const 和 let 遇到 TDZ 会立刻报错,反而帮你快速定位 class 位置问题。所以:
- 统一用
const声明类(class本身就是块级绑定) - 实例变量优先用
let声明,留出赋值空间 - 不依赖“能跑通”来判断正确性,而是让 TDZ 把隐患提前暴露出来


















