You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于JavaScript提升、暂存死区的代码运行差异问题及资料推荐

变量提升(Hoisting)与暂时性死区(TDZ)的差异解析

哈哈,这个问题问到点子上了——这两个代码的差异确实和变量提升(hoisting)密切相关,而且刚好和暂时性死区(TDZ)的规则交织在一起,咱们一点点拆解来看:

先看能正常运行的按钮点击代码

对应的JavaScript代码:

const btn = document.getElementById("btn"); 
btn.onclick = function() { 
  printMe(obj); 
}; 

function printMe(person) { 
  console.log(person.firstName, person.lastName); 
} 

const obj = { firstName: "John", lastName: "Wick" };

配套的HTML:

<button id="btn">Click me!</button>

这个代码能跑的核心原因是按钮点击是异步触发的:当页面加载完成后,obj已经被成功初始化,脱离了暂时性死区;同时printMe作为函数声明,会被完全提升到当前作用域的顶部——所以当你点击按钮触发事件时,printMe已经可用,obj也早就准备好,自然能正常打印结果。

再看无法运行的直接调用代码

printMe(obj); 

function printMe(person) { 
  console.log(person.firstName, person.lastName); 
} 

const obj = { firstName: "John", lastName: "Wick" };

这里的问题出在执行顺序上:

  • 函数声明printMe会被完全提升(包括函数体),所以第一行调用printMe的时候,函数本身是存在的;
  • 但obj是用const声明的,它的声明会被提升,但不会被初始化——这就进入了暂时性死区(TDZ)。在执行到const obj = ...这行代码之前,任何对obj的引用都会抛出ReferenceError。所以当第一行调用printMe(obj)时,obj还在TDZ里,直接报错。

核心结论

这两个代码的差异本质就是不同类型声明的提升规则差异:

  • 函数声明会被完全提升,在作用域内任何位置都能调用;
  • let/const声明的变量只会提升声明,不会提升初始化,在声明语句执行前处于TDZ,无法被引用。

推荐阅读资料

  • MDN文档中的「变量提升(Hoisting)」章节,详细讲解了不同类型声明的提升规则
  • MDN文档中的「暂时性死区(Temporal Dead Zone)」章节,深入解释TDZ的触发场景和影响
  • 《你不知道的JavaScript(上卷)》的「作用域与闭包」部分,对提升和TDZ有非常透彻的实战解析

内容的提问来源于stack exchange,提问作者d_oram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:26:17