首頁  >  問答  >  主體

導入模組是否意味著將模組的程式碼嵌入到導入語句所在的行嗎?

從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粉269847997399 天前389

全部回覆(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
  • 取消回覆