一、文法運作方式
CommonJs子產品的require是同步加載子產品,
- require指令加載某個子產品時,會運作整個代碼。
- require加載同一個子產品時,将會讀取緩存
ES6子產品的import是異步加載子產品
二、加載方式
CommonJS子產品是運作時加載
以下代碼的實質是整體加載fs子產品(即加載fs的所有方法),生成一個對象(_fs),然後再從這個對象上面讀取 3 個方法。這種加載稱為“運作時加載”,因為隻有運作時才能得到這個對象,導緻完全沒辦法在編譯時做“靜态優化”
// CommonJS子產品
let { stat, exists, readfile } = require('fs');
// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;
ES6子產品是編譯時輸出接口
以下代碼的實質是從fs子產品加載 3 個方法,其他方法不加載。這種加載稱為“編譯時加載”或者靜态加載,即 ES6 可以在編譯時就完成子產品加載,效率要比 CommonJS 子產品的加載方式高。當然,這也導緻了沒法引用 ES6 子產品本身,因為它不是對象。ES6的import會提升至開頭
三、輸出值的差別
CommonJS子產品化:對輸出值的複制
//exCommon.js
let count = 1;
function incCount() {
count++;
}
module.exports = {
count,
incCount
}
//useCommon.js
const C_mdu = require('./exCommon');
console.log(C_mdu.count);//1
C_mdu.incCount();
console.log(C_mdu.count);//1
- 對于基本資料類型,為直接複制,即子產品中值再發生改變不影響已引入子產品值
- 對于引用類型,為淺拷貝,因與子產品中值為一個指針,即值互相影響
ES6子產品化:對值的引用 【動态隻讀引用】
//exES.js
let count = 1;
function incCount() {
count++;
}
module.exports = {
count,
incCount
}
//useES.js
import * as ES_mdu from './exES.js';
console.log(ES_mdu.count);//1
ES_mdu.incCount();
console.log(ES_mdu.count);//2
- 對于隻讀,import指令将會生成一個隻讀引用,不可在子產品外修改
- 對于動态,原始值發生改變時,import加載的值一樣會發生改變
四、循環加載
案例文章 - CSDN - commonjs和ES6及requirejs子產品循環引用
CommonJs : 循環加載時,屬于加載時執行。即腳本代碼在require的時候,就會全部執行。一旦出現某個子產品被"循環加載",就隻輸出已經執行的部分,還未執行的部分不會輸出。
ES6:循環加載時,ES6子產品是動态引用。隻要兩個子產品之間存在某個引用,代碼就能夠執行。
五、使用方法
CommonJs
module.exports 和exports倆者無差別,exports為node簡化文法,最終暴露的結果,都是以 module.exports 所指向的對象為準。
exports.xxx,相當于在導出對象上挂屬性,該屬性對調用子產品直接可見
exports =相當于給exports對象重新指派,調用子產品不能通路exports對象及其屬性
//exCommon.js
//commonJs子產品化 導出
let count = 1;
function incCount() {
count++;
console.log("CommonJs目前計數為:",count);
}
module.exports = {
count,
incCount
}
//useCommon.js
//commonJs子產品化 導入
const C_mdu = require('./exCommon');
console.dir(C_mdu);//{ count: 1, incCount: [Function: incCount] }
ES6
//exES.js
//ES6子產品化 導出方法一
export let count = 1;
export function incCount() {
count++;
console.log("ES6,目前計數為:" + count);
}
//useES.js
//ES6子產品化 導入方法一
import { count, incCount } from "./exES.js";
//ES6子產品化 導入方法二 as起别名
import * as ES_mdu from "./exES.js";
console.dir(ES_mdu);//{ count: 1, incCount: [Function: incCount] }
es6使用export default
// 如果一個js子產品檔案就隻有一個功能, 那麼就可以使用export default導出
// 一個子產品不能具有多個預設導出
// 暴露.js
export default {
name: 'xiaoming',
age: 18
};
// 引用.js
import person from '暴露.js'
參考文章 - CommonJS和ES6子產品化的差別
參考文章 - commonjs與es6子產品化有什麼差別