实践机制:变量提升(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。- 函数声明可直接调用,函数表达式按变量规则。