跳到主要内容

实践机制:变量提升(Hoisting)到底怎么回事?TDZ 是什么?

面试速答(30 秒版 TL;DR)

  • 面试常说的“提升”指:在代码执行前,引擎会先处理声明(创建绑定),因此你会看到“声明好像被挪到了顶部”的效果。
  • var:声明被提升且初始化为 undefined,因此“先用后声明”不会报错(但值是 undefined)。
  • let/const:声明会提升但不会初始化,在声明之前访问会触发 TDZ(Temporal Dead Zone,暂时性死区) 报错。
  • 函数声明(function f(){})整体可用;函数表达式(const f = () => {})遵循变量规则。

说明:你给的主题是“实践机制”,在 JS 面试语境里通常对应“提升机制(Hoisting)”。本文按提升机制展开。


最小例子:var vs let/const

console.log(a); // undefined
var a = 1;
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 1;

解释要点:

  • var a 在创建阶段就有了绑定并初始化为 undefined
  • let b 有绑定但未初始化,访问落在 TDZ。

函数提升:声明 vs 表达式

f(); // ok
function f() {}
g(); // ReferenceError(或 TypeError,取决于写法与位置)
const g = function () {};

面试口述版结论:

  • 函数声明会提升可用(常被称为“提升更彻底”)。
  • 函数表达式本质是变量赋值,受 var/let/const 规则影响。

TDZ 的意义(为什么要这样设计)

你能说清“设计动机”会更像理解而不是背诵:

  • 让块级作用域变量在声明前不可用,减少“读到 undefined 但不报错”的隐患。
  • 让代码更可预测,和 const 的“必须初始化”语义一致。

典型题 & 标准答法

Q1:var 为什么不推荐?

  • 没有块级作用域(函数级作用域),容易污染与复用冲突。
  • 提升 + 初始化为 undefined 容易隐藏 bug。

Q2:let/const 也提升,为什么还会报错?

答法要点:

  • 提升的是“声明/绑定”,不是“初始化”。
  • 在初始化前的区域就是 TDZ,访问会报错。

易错点/坑

  • 把“提升”理解成“代码真的移动”:不是,这是执行模型导致的表现。
  • typeof 在 TDZ 变量上也会报错(不像对未声明变量那样安全)。

速记要点(可背诵)

  • var:提升 + 初始化 undefined
  • let/const:提升但不初始化,声明前是 TDZ。
  • 函数声明可直接调用,函数表达式按变量规则。