从ReferenceError: can't access lexical declaration 'X' before initialization - JavaScript | MDN中,有一个无效导入的示例:
a.js
(入口模块):
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;
MDN解释:
在这个例子中,导入的变量
a
被访问,但是未初始化,因为a.js
的评估被当前模块b.js
的评估阻塞。
我理解这个意思是导入一个模块意味着将模块的代码嵌入到导入语句的行。也就是说,编译时a.js
变成了这样:
console.log(a); // ReferenceError: Cannot access 'a' before initialization const b = 1; const a = 2;
这个理解正确吗?我没有在import - JavaScript | MDN中看到这个解释。由于变量提升,我不知道如何测试这个问题,因为重新排列a.js
中的行不会改变结果。
P粉1658237832023-09-17 00:53:49
从导入的模块中的代码不仅仅是嵌入("粘贴"),而是存在于一个独立的闭包中。虽然这肯定是一个过度简化,但我将模块与函数进行比较,将export
语句与其return
语句进行比较:
function a_js() { var b = b_js(); // 不必要的行 return 2; } function b_js() { var a = a_js(); console.log(a); return 1; }
<button onclick="a_js()">import a.js</button> <button onclick="b_js()">import b.js</button>
因为模块相互导入,它们不能以任何顺序加载:按下任何按钮都会导致"Maximum call stack size exceeded"错误。
但是如果你删除不必要的行(只是填充一个然后被丢弃的局部变量),它就可以工作。