CommonJS模組與ES6模組的區別
一.CommonJS模組與ES6模組的區別
- CommonJS模組輸出的是一個值的拷貝,ES6模組輸出的是值的引用。
- CommonJS模組是執行時載入,ES6模組是編譯時輸出介面。
- CommonJS模組的require()是同步載入模組,ES6模組的import命令是非同步載入,有一個獨立的模組依賴的解析階段。
第二個區別是因為CommonJS載入的是一個物件(即module.exports屬性),該物件只有在指令碼執行完才會生成。而ES6模組不是物件,它的對外介面只是一種靜態定義,在程式碼靜態解析階段就會生成。
第一個區別
CommonJS模組輸出的是值的拷貝,也就是說,一旦輸出一個值,模組內部的變化就影響不到這個值。例如:
上面程式碼輸出內部變數counter和改寫這個變數的內部方法incCounter。然後,在main.js裡面載入這個模組。
上面程式碼說明,lib.js模組載入之後,它的內部變化就影響不到輸出的mod.counter了。這是因為mod.counter是一個原始型別的值,會被快取。除非寫成一個函式,才能得到內部的值。例如:
上面程式碼中,輸出的counter屬性實際上是一個取值器函式。現在再執行main.js,就可以正確讀取內部變數counter的變動了。
ES6模組的執行機制與CommonJS不一樣。JS引擎對指令碼靜態分析的時候,遇到模組載入命令import
上面程式碼說明,ES6模組輸入的變數counter是活的,完全反應其所在模組lib.js內部的變化。
再說一個出現在export中的例子:
上面程式碼表明,ES6模組不會快取執行結果,而是動態地去被載入模組取值,並且變數總是繫結其所在的模組。
上面程式碼中,main.js從lib.js輸入變數obj,可以對obj新增屬性,但是不能重新賦值。因為變數的地址是隻讀的。
最後,export通過介面,輸出的是同一個值。不同的指令碼載入這個介面,得到的都是同樣的例項。例如:
上面的指令碼mod.js,輸出的是一個c的例項。不同的指令碼載入這個模組,得到的都是同一個例項。
這就證明了x.js和y.js載入的都是c的同一個例項。