區別CommonJS和ES6 Module
阿新 • • 發佈:2020-07-16
區別CommonJS和ES6 Module
1. 靜態和動態
- 兩者模組規範最本質區別就是,CommonJS對模組依賴的解決是動態的,而ES6 Module對模組的解決是靜態的,舉個例子:
// CommonJS
require(test ? 'a.js' : 'b.js');
// require()的引數可以是變數、表示式,所以不執行程式碼,根本不知道匯入的是哪一個模組,
// ES6 Module
import {a} form './a.js';
// 匯入路徑必須是真實的url字串。所以,在程式碼編譯的時候,就能夠得到到模組之間的依賴關係,進而形成一種靜態的模組結構。
- 因此,ES6 Module有以下優點:
- 檢測和排除無用程式碼,減少webpack打包體積
- 有助於確認模組之間傳遞的值或介面型別是否正確。
- CommonJs的本質是匯入一個物件,而ES6 Module支援直接匯入一個變數
2. 值拷貝和動態對映
- CommonJS的匯入,就是值的拷貝,被拷貝到的變數依舊是可以改的
let a = require('a.js').num;
// 就是把require('a.js').num的值拷貝一份賦值給a而已,a依舊是可以被任意賦值的變數
- ES6 Module的匯入,是值的對映,並且這個對映只讀
// a.js export let a = 0; export let add = ()=>{ a++; } // index.js import {a, add} from 'a.js'; console.log(a); // 0 add(a); // 去到a.js的作用域裡操作a++ console.log(a); // 1 a++; // 報錯,a不可改
總結
- 瞭解模組,是學習Webpack的必經之路。舉個例子,在webpack裡,對於模組的require,具體程式碼實現如下:
// The require function function __webpack_require__(moduleId) { ... // Check if module is in cache if(installedModules[moduleId]) { return installedModules[moduleId].exports; } // Create a new module (and put it into the cache) var module = installedModules[moduleId] = { i: moduleId, l: false, exports: {} // 預設匯出值 }; ... return module.exports; }
- 所以,對於CommonJS模組規範,可以這樣理解:
- 第一次匯入,就會執行一次js程式碼,並把最後的匯出結果記錄到cache裡,第二次再匯入,直接從cache裡提取。這就是為什麼只有第一次require會執行程式碼以及每一次require得到的都是同一個物件的原因。
- CommonJS出現了迴圈依賴的時候(一個被require的js還沒有執行到module.exports,這個時候cache裡面會存在一個它的匯出初始值,然後這個js再次被require的時候),就會直接從cache匯出,匯出的就是預設的匯出值:一個空物件{}。
// foo.js
let bar = require('./bar.js');
console.log("value of bar:" + bar);
module.exports = 'This is foo.js';
// bar.js
let foo = require('./foo.js');
console.log("value of foo:" + foo);
module.exports = 'This is bar.js';
// index.js
require('./foo.js');
// 輸出結果:
// value of foo: {}
// value of bar: This is bar.js