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)行時加載
參考文檔: