JavaScript模塊化

CommonsJS

module:模塊標(biāo)識

require: 模塊引用

export:模塊輸出

CommonJS一個模塊就是一個腳本文件,require命令第一次加載腳本時,就會執(zhí)行整個腳本,然后在緩存中生成一個對象

```

module:{

????id: "... ",? ? ????????// 模塊名

? ? exports: {...},? ? // 模塊導(dǎo)出的接口

? ? loaded: true,? ? // 模塊是否加載完畢

? ? ... ????????????????????// 其他屬性

}

```

需要用到這個模塊時,就會取到exports屬性上取值,之后再執(zhí)行require命令,也不會再執(zhí)行該模塊,而是到緩存中取值。

若模塊內(nèi)的值會改變(例如模塊內(nèi)有定時器),若每次都要獲取到模塊內(nèi)的最新值,需要每次更新數(shù)據(jù)時都更新module.exports

CommonJS是同步加載模塊,這對于服務(wù)端來說不是問題,NodeJS采用了這個規(guī)范,所有的模塊都放在本地硬盤,等待模塊時間就是讀取文件的時間,時間很短。

但是對于瀏覽器而言,它需要從服務(wù)器加載模塊,涉及到網(wǎng)速、代理等因素,一旦等待時間過長,瀏覽器處于假死狀態(tài),所以這時在瀏覽器端就不適合用CommonJS了。

AMD(Asynchronous Module Definition 異步模塊定義)

AMD采用異步方式加載模塊,模塊的加載不影響它后面的語句執(zhí)行。這里的異步指的是不阻塞瀏覽器其他任務(wù)(dom構(gòu)建等),而加載內(nèi)部則是同步的(加載完模塊后立即執(zhí)行回調(diào)函數(shù))

AMD也采用require命令加載模式,但與CommonJS不同,它需要兩個參數(shù):require([module],callback)

[module]:是一個數(shù)組,里面的成員是需要加載的所有模塊,callback是加載完成后的回調(diào)函數(shù)

```

require(['math'],function(math){

? ? math.add(1,2);

})

```

AMD規(guī)范是為推廣requireJS產(chǎn)生的

模塊的定義:define(id?, dependencies?, factory);?

id: 模塊名

dependencies: 模塊的依賴

factory: 模塊的工廠函數(shù),模塊初始化要執(zhí)行的函數(shù)或?qū)ο螅绻呛瘮?shù),只執(zhí)行一次,如何是對象,就是模塊的輸出

```

//無模塊依賴的模塊定義 math.js

define(function(){

? ? ...

});

//有模塊依賴的模塊定義 math.js

define(["dependenceModule"],function(dependenceModule){

...

});

//模塊加載

require(["math"],function(math){

...

})

```

當(dāng)require函數(shù)加載math模塊時,會先加載dependenceModule模塊,當(dāng)有多個依賴時,將所有的依賴都寫在define函數(shù)第一個參數(shù)數(shù)組中,所以AMD是依賴前置的。


CMD(Common Module Definition)

CMD推崇依賴就近,延遲執(zhí)行

define(factory);

factory為函數(shù)時,表示是模塊的構(gòu)造方法,執(zhí)行該函數(shù)的構(gòu)造方法,可以得到模塊向外提供的接口。

factory方法在執(zhí)行時,默認(rèn)會傳入三個參數(shù): require, exports, module

```

//CMD

define(function(require, exports, module){

? ? var a = require('./a.js');

});

```

CMD規(guī)范起源于Sea.js的推廣,傾向于在使用過程中提出依賴,不需要像AMD一樣,必須在最前面寫好依賴。

UMD(Universal Module Definition)

UMD是AMD和CommonJS的糅合

AMD模塊以瀏覽器第一的原則發(fā)展,異步加載模塊

CommonJS模塊以服務(wù)器第一的原則發(fā)展,同步加載模塊。它的模塊時無需包裝的

UMD先判斷是否支持NodeJS的模塊(exports)是否存在,存在則使用NodeJS模塊加載的方式,再判斷AMD\CMD(define)是否存在,存在則使用AMD\CMD的方式加載模塊。

```

(function(root, factory){

? ? if(typeof exports === "object"){

? ? ? ? module.exports = factory(); //CommonJS

????}else if(typeof define === "function" && define.amd){

? ? ? ? define(factory); //AMD

????}else{

? ? ? ? return {

????????????addEvent: function(el, type, handle){

? ? ? ? ? ? ? ? ...

????????????},

? ? ? ? ? ? removeEvent: function(el, type, handle){

? ? ? ? ? ? ? ? ...

????????????}

????????}

????}

});

```

ES6

ES6與CommonJS類似,但又不同:

1、ES6模塊輸出的是值得引用,輸出接口動態(tài)綁定,不是生成輸出的輸出對象的拷貝,所以引用模塊的位置可以動態(tài)關(guān)聯(lián)模塊中的值;而CommonJS輸出的是值得拷貝

2、ES6模塊編譯時執(zhí)行,靜態(tài)編譯,會導(dǎo)致:import命令會被JavaScript引擎靜態(tài)分析,優(yōu)先與模塊內(nèi)的其他內(nèi)容的執(zhí)行;export命令會有變量聲明提前的效果。 而CommonJS模塊總是在運(yùn)行時加載

參考文檔:

深入理解 ES6 模塊機(jī)制

JS模塊化加載之CommonJS、AMD、CMD、ES6

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容