关于JavaScript作用域与Hoisting(变量提升)的新手疑问求解
问题核心原因:const/let 存在暂时性死区(Temporal Dead Zone,简称TDZ)
你对作用域和变量提升的认知存在部分偏差,核心是没有区分不同声明类型的提升行为差异:
不同声明类型的提升规则
- 函数声明的提升:会同时将声明、函数体定义都提升到当前作用域顶部,因此无论在声明前还是声明后调用都可以正常执行,这也是你前两个例子中函数调用不会报错的原因。
var声明的提升:仅将声明提升到作用域顶部,初始化值为undefined,提前访问只会拿到undefined,不会抛出引用错误。const/let声明的提升:确实会将声明提升到当前作用域顶部,但不会提前完成初始化,从作用域顶部到变量正式完成赋值的这段区间,就是该变量的暂时性死区,在死区内访问该变量会直接抛出ReferenceError。
针对第三个报错案例的执行逻辑拆解
你的第三段代码:
function test() { console.log(`${firstName}`) }; test(); const firstName = 'a';
实际执行顺序如下:
- 全局作用域预解析阶段:首先提升函数声明
test,同时提升const firstName的声明(但不做初始化,firstName进入暂时性死区) - 逐行执行代码阶段:
- 先调用
test(),函数内部尝试访问firstName,此时firstName还处于全局作用域的暂时性死区内,未完成初始化,因此直接抛出引用错误 - 后续才会执行到
const firstName = 'a',这一步才会结束暂时性死区,给变量完成赋值
- 先调用
补充验证小技巧
你可以观察报错信息:第三段代码的报错是Cannot access 'firstName' before initialization,而非firstName is not defined,这也说明JS已经识别到全局作用域下存在firstName的声明,只是还没初始化,足以证明const是存在提升行为的。
内容的提问来源于stack exchange,提问作者Nattttt
相关产品推荐
相关产品推荐

