ES6 module載入機制

FrancisXu發表於2019-04-25

找遍度娘,發現好多文章都是拿來主義,阮一峰老師ECMAScript6入門的文件各種花式開枝散葉,語法上阮一峰老師講的已經非常細緻了,但是概念上的東西我還是有點模糊。

文件裡講了ES6模組載入和CommonJS的區別(ES5的模組引用表現形式可能有些不同,但本質其實都是把模組作為物件引用,所以這個區別也是ES6和ES5模組引用的區別):

1.CommonJS 模組輸出的是一個值的拷貝,ES6 模組輸出的是值的引用

2.CommonJS 模組是執行時載入,ES6 模組是編譯時輸出介面。

我這人比較懶,不太習慣單純的copy,強烈推薦大家先看一下阮一峰老師的ECMAScript 6 入門

文件裡針對這兩點做了詳細的解釋,針對第一點解釋說ES6 模組不是物件,那我就想知道不是物件他到底是什麼,百度了好久,終於在google搜尋的第一篇的文章裡找到了答案:

每一個 ES6 模組都是一個包含 JS 程式碼的檔案,模組本質上就是一段指令碼,而不是用module關鍵字定義一個模組。其實我想知道的就是這句話, ES6 模組是指令碼。

根據上面得到的概念,不難理解CommonJS 模組是執行時載入,ES6 模組是編譯時輸出介面。 CommonJS的模組本質是一個物件的引用,因此需要執行時載入。而ES6的module其實就是引入了一個新的概念,模組不是物件而是指令碼,這樣就可以在編譯的時候載入。

至於CommonJS 模組輸出的是一個值的拷貝,ES6 模組輸出的是值的引用。這個點我們可以想象一下import和export到底做了什麼,它們在程式載入的時候組成一對不同於"="的對應關係。

舉個例子
case1 CommonJS模組引用

//a.js
let func=require('./b').func,
     a=require('./b').b;
a=1;
func();//輸出2

//b.js
let b=2;
function func() {
    console.log(b);
}
module.exports = {
    func: func,
    b: b
};
複製程式碼

case2 ES6模組引用

//a.mjs
import {b as a}  from "./b.mjs"
import {func}  from "./b.mjs"
a=1;//報錯
func();

//b.mjs
export function func() {
    console.log(b)
}
export let b=2;
複製程式碼

再來一張在下的大作

ES6 module載入機制

正常情況下,我們把一個存放值的變數b賦值給變數a,其實就是把b裡面存放的值放進a的儲存空間中,這一點沒什麼異議。而case1這種情況,CommonJS 模組是一個正常的JS物件,a=require('./b').b等同於a=b 所以遵循JS的變數賦值的規則。

ES6 模組輸出的是值的引用。在ES6中,case3這種情況下,如果我們試圖直接修改a的值會報錯,因為a不是b,a是指向變數b的變數,如果要修改a的值,只有在被引用的模組裡修改b的值,a的值才會發生改變。所以我們可以認為export和import帶來的關係是,a的儲存空間指向變數b,並且這個關係不可以被破壞。

參考

[深入淺出 ES6(十六):模組 Modules]www.infoq.cn/article/es6… ECMAScript 6 入門

相關文章