ReferenceError: 无法在初始化之前访问词法声明 'X'

当在初始化之前访问词法变量时,会发生 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)

错误类型

哪里出错了?

在初始化之前访问了词法变量。当在任何作用域(全局、模块、函数或块)中在声明变量的位置执行之前访问使用 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;

另请参阅