参考错误:初始化之前无法访问词法声明 'X'

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

¥The JavaScript exception "can't access lexical declaration *variable*' before initialization" occurs when a lexical variable was accessed before it was initialized. This happens within any scope (global, module, function, or block) when [let](/en-US/docs/Web/JavaScript/Reference/Statements/let) or [const`](/en-US/docs/Web/JavaScript/Reference/Statements/const) variables are accessed before the place where they are declared is executed.

信息

¥Message

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

错误类型

¥Error type

ReferenceError

什么地方出了错?

¥What went wrong?

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

¥A lexical variable was accessed before it was initialized. This happens within any scope (global, module, function, or block) when variables declared with let or const are accessed before the place where they are declared has been executed.

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

¥Note that it is the execution order of access and variable declaration that matters, not the order in which the statements appear in the code. For more information, see the description of Temporal Dead Zone.

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

¥This issue does not occur for variables declared using var, because they are initialized with a default value of undefined when they are hoisted.

当模块使用依赖于正在评估的模块本身的变量时,在 循环导入 中也可能会出现此错误。

¥This error can also occur in cyclic imports when a module uses a variable that depends on the module itself being evaluated.

示例

¥Examples

无效案例

¥Invalid cases

在本例中,变量 foo 在声明之前被访问。此时 foo 尚未使用值进行初始化,因此访问该变量会引发引用错误。

¥In this case, the variable foo is accessed before it is declared. At this point foo has not been initialized with a value, so accessing the variable throws a reference error.

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 的计算阻止。

¥In this example, the imported variable a is accessed but is uninitialized, because the evaluation of a.js is blocked by the evaluation of the current module 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;

有效案例

¥Valid cases

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

¥In the following example, we correctly declare a variable using the const keyword before accessing it.

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

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

¥In this example, the imported variable a is asynchronously accessed, so both modules are evaluated before the access to a occurs.

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;

也可以看看

¥See also