为何两段JavaScript代码运行结果不同?一段报ReferenceError一段正常
JavaScript词法环境与暂时性死区问题解析
问题根源:暂时性死区(TDZ)
你碰到的这个报错,核心原因是let声明的变量存在暂时性死区,这和JavaScript词法环境的创建逻辑直接相关,和你预期的“先找外层变量再报错”完全不同。
两段代码的执行差异
报错代码的运行过程
let x = 1; function func() { console.log(x); let x = 2; } func();
当调用func时,函数的执行上下文会先创建自己的词法环境:
- 第一步就会扫描整个函数作用域,把所有
let/const声明的变量(这里就是x)注册到当前词法环境里,但不会给它们赋值。 - 从这时候开始,到
let x = 2执行完成前,这个x就处于暂时性死区——它已经被声明了,但完全不可访问,任何对它的引用都会直接抛出ReferenceError。 - 所以
console.log(x)执行时,JavaScript会优先找当前作用域的x,但这个x还在TDZ里,根本不会去外层全局作用域找那个x=1,直接报错。
正常代码的运行过程
let x = 1; function func() { console.log(x); } func(); // logs out 1
这段代码里,func内部没有声明自己的x,所以执行console.log(x)时,JavaScript会沿着作用域链往上找,找到全局作用域里已经初始化完成的x,自然就输出1了。
关键知识点总结
var声明的变量会被提升并默认赋值undefined,但let/const只提升声明,不做初始化,直接进入暂时性死区。- 在暂时性死区内引用变量,不会去外层作用域查找,直接报错——这是
let/const和var最核心的区别之一。 - 词法环境的创建分两步:先注册变量,再执行赋值初始化,暂时性死区就是这两步之间的“真空期”。
内容的提问来源于stack exchange,提问作者The Curious Cat
相关产品推荐
相关产品推荐

