天天看點

ES6子產品化與CommonJs子產品化

一、文法運作方式

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子產品化有什麼差別