ReferenceError: can't access lexical declaration 'X' before initialization

JavaScript 异常“无法在初始化前访问词法声明 'X'”发生在词法变量在初始化前被访问时。当在变量声明的位置执行之前,访问了使用 letconst 声明的变量时,这种情况会在任何作用域(全局、模块、函数或块)内发生。

消息

ReferenceError: Cannot access 'X' before initialization (V8-based)
ReferenceError: can't access lexical declaration 'X' before initialization (Firefox)
ReferenceError: Cannot access uninitialized variable. (Safari)

错误类型

ReferenceError

哪里出错了?

词法变量在初始化之前被访问。当在声明变量的位置执行之前,访问了使用 letconst 声明的变量时,这种情况会在任何作用域(全局、模块、函数或块)内发生。

请注意,重要的是访问和变量声明的执行顺序,而不是语句在代码中出现的顺序。有关更多信息,请参阅 暂时性死区 的描述。

使用 var 声明的变量不会出现此问题,因为它们在 变量提升 时会用默认值 undefined 进行初始化。

当一个模块使用依赖于模块本身进行评估的变量时,此错误也可能发生在 循环导入 中。

示例

无效案例

在此情况下,变量 foo 在声明之前被访问。此时 foo 尚未用值进行初始化,因此访问该变量会抛出引用错误。

js
function test() {
  // Accessing the 'const' variable foo before it's declared
  console.log(foo); // ReferenceError: foo is not initialized
  const foo = 33; // 'foo' is declared and initialized here using the 'const' keyword
}

test();

在此示例中,导入的变量 a 被访问但未初始化,因为 a.js 的评估被当前模块 b.js 的评估所阻塞。

js
// -- a.js (entry module) --
import { b } from "./b.js";

export const a = 2;

// -- b.js --
import { a } from "./a.js";

console.log(a); // ReferenceError: Cannot access 'a' before initialization
export const b = 1;

有效情况

在以下示例中,我们在访问变量之前,使用 const 关键字正确声明了变量。

js
function test() {
  // Declaring variable foo
  const foo = 33;
  console.log(foo); // 33
}
test();

在此示例中,导入的变量 a 是异步访问的,因此在访问 a 之前,两个模块都会进行评估。

js
// -- a.js (entry module) --
import { b } from "./b.js";

export const a = 2;

// -- b.js --
import { a } from "./a.js";

setTimeout(() => {
  console.log(a); // 2
}, 10);
export const b = 1;

另见