搜索

首页  >  问答  >  正文

导入模块是否意味着将模块的代码嵌入到导入语句所在的行吗?

从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粉269847997P粉269847997439 天前434

全部回复(1)我来回复

  • P粉165823783

    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"错误。

    但是如果你删除不必要的行(只是填充一个然后被丢弃的局部变量),它就可以工作。

    回复
    0
  • 取消回复