目前主流的JavaScript模塊化實(shí)現(xiàn)的技術(shù)以及它們之間的區(qū)別。

目前主流的JavaScript模塊有CommonJS嫉拐、AMD哩都、CMD、以及ES的模塊系統(tǒng)婉徘。

一漠嵌、CommonJS

commonJS的出發(fā)點(diǎn):js沒有完善的模塊系統(tǒng),但是隨著NodeJS的出現(xiàn)盖呼,讓js可以在任意地方運(yùn)行儒鹿,因此具備了大型項(xiàng)目的開發(fā)能力,CommonJS也在此時(shí)應(yīng)運(yùn)而生几晤。
NodeJS是commonJS的主要實(shí)踐者约炎,有四個(gè)環(huán)境變量Module,exports蟹瘾,require圾浅,global為它提供支持,實(shí)際使用時(shí)憾朴,用module.exports導(dǎo)出模塊(定義當(dāng)前模塊對(duì)外輸出的接口)贱傀,require加載模塊。

commonJS使用同步的方式加載模塊伊脓,在本地時(shí)府寒,因?yàn)槟K文件儲(chǔ)存在磁盤中,讀取速度很快报腔,所以沒有問題株搔,但是在瀏覽器中,因?yàn)榫W(wǎng)絡(luò)的問題纯蛾,所以更合理的方法是采用異步的方法纤房。
-暴露方法>module.exports = value或exports.xxx = value
-引入模塊>const xxx = require(xxx)

commonJS規(guī)范
1.一個(gè)文件就是一個(gè)模塊,具有單獨(dú)的作用域翻诉。
2.普通方式定義的變量炮姨、函數(shù)捌刮、對(duì)象都屬于該作用域中。
3.通過require加載模塊舒岸。
4.通過exports和module.exports來暴露模塊中的內(nèi)容绅作。
注意:
1.exports是module.exports的子集
2.所有代碼運(yùn)行在指定的模塊中,不會(huì)污染全局作用域
3.模塊可以被多次加載蛾派,但是只會(huì)在第一次加載時(shí)執(zhí)行俄认,之后就會(huì)講運(yùn)行結(jié)果緩存進(jìn)行下一次使用。
4.模塊加載順序洪乍,按照模塊出現(xiàn)的順序進(jìn)行加載眯杏。
5._dirname代表當(dāng)前文件所在的文件夾路徑
6._filename代表當(dāng)前模塊文件所在的文件夾路徑+文件名
7.當(dāng)exports和module.exports同時(shí)存在,module.exports會(huì)覆蓋exports壳澳。
8.當(dāng)模塊內(nèi)全是exports時(shí)岂贩,就相當(dāng)于module.exports

二、ES6模塊化

es6模塊化語(yǔ)言旨在成為瀏覽器和服務(wù)器的通用模塊解決方案巷波,通過export導(dǎo)出模塊萎津,通過import引入模塊,es6還提供了默認(rèn)導(dǎo)出的exports default命令褥紫,為模塊增加指定輸出,對(duì)應(yīng)的import不需要大括號(hào)瞪慧。
es6模塊不是對(duì)象髓考,import命令會(huì)被js引擎靜態(tài)分析(安全的編譯,優(yōu)化性能弃酌,靜態(tài)的將代碼加載到引用了的文件氨菇?具體不太懂,了解清楚后會(huì)發(fā)文)妓湘,編譯時(shí)就會(huì)引入模塊的代碼查蓉,而不是在代碼運(yùn)行的時(shí)候去加載,所以無法實(shí)現(xiàn)按條件加載榜贴。也正是因?yàn)檫@個(gè)豌研,使靜態(tài)加載成為可能。
1.export 將模塊中的代碼對(duì)外暴露唬党,可以導(dǎo)出的是一個(gè)對(duì)象包含的多個(gè)屬性方法鹃共,export.default只能導(dǎo)出一個(gè)可以不具名的函數(shù),我沒可以通過import引用驶拱,同時(shí)我沒也可以用require引入霜浴,因?yàn)閣ebpack引起了server相關(guān)。
2.import 引入需要用到的模塊蓝纲,在編譯時(shí)就會(huì)引入阴孟,所以不存在按需引入晌纫。

import {fn} from './xxx/xxx'(export的導(dǎo)出方式的引用方式)
import fn from './xxx/xxx1'(export.default的到處方式的引用方式)

三、AMD

Asynchronous Module Definition永丝,異步加載模塊锹漱。它是一個(gè)在瀏覽器端模塊化開發(fā)的規(guī)范,不是原生js的規(guī)范类溢,使用AMD進(jìn)行模塊開發(fā)需要使用到RequireJS函數(shù)庫(kù)凌蔬。
AMD規(guī)范采用異步方式加載模塊,模塊的加載不影響后續(xù)代碼的執(zhí)行闯冷,所有依賴這個(gè)模塊的語(yǔ)句都會(huì)定義一個(gè)回調(diào)函數(shù)砂心,當(dāng)模塊加載完成后會(huì)執(zhí)行這個(gè)回調(diào)函數(shù)。
使用require.js實(shí)現(xiàn)AMD規(guī)范的模塊化:用require.config()指定引用路徑等蛇耀,用defined()定義模塊辩诞,用require()引入模塊。

//定義模塊
defined('moduleName',['a','b'],function(ma,mb){
  return someExportValue
})  
//引入模塊
require(['a','b'],function(ma,mb)){
  //*code*
}

1.函數(shù)庫(kù)requireJS主要解決的問題
-文件可能存在依賴關(guān)系纺涤,被依賴的文件需要早于依賴它的文件加載到瀏覽器中译暂。
-js在加載的時(shí)候?yàn)g覽器會(huì)停止頁(yè)面渲染,加載文件越多撩炊,頁(yè)面的響應(yīng)時(shí)間就會(huì)越長(zhǎng)外永。
-異步加載前置
2.語(yǔ)法
define(id,dependencies,factory)
-id 可選參數(shù),用來定義模塊的標(biāo)識(shí)拧咳,如果沒有提供該參數(shù)伯顶,將使用腳本文件名(去掉拓展名)
-dependencies是一個(gè)當(dāng)前模塊用來的模塊名稱數(shù)組。
-factory骆膝,工廠方法祭衩,模塊初始化要執(zhí)行的函數(shù)或是對(duì)象,如果是函數(shù)阅签,他應(yīng)該制備執(zhí)行一次掐暮,如果是對(duì)象,此對(duì)象應(yīng)該為模塊的輸出值政钟。

四路克、CMD

CMD是另一種js模塊化方案,它與AMD很類似养交,不同點(diǎn)在于:AMD推崇依賴前置衷戈、提前執(zhí)行,CMD推崇依賴就近层坠、延遲執(zhí)行殖妇。此規(guī)范其實(shí)是在sea.js推廣過程中產(chǎn)生的。
因?yàn)镃MD推從一個(gè)文件一個(gè)模塊破花,所以經(jīng)常就用文件名作為模塊id谦趣;CMD推推崇依賴就近疲吸,所以一般不再define的參數(shù)中寫依賴,而是在factory中寫
define(id,deps,factory)
factory有三個(gè)參數(shù):function(require,exports,module){}
1.require參數(shù)是第一個(gè)參數(shù)前鹅,是一個(gè)方法摘悴,接收模塊標(biāo)識(shí)作為唯一參數(shù),用來獲取其它模塊提供的接口舰绘;
2.exports蹂喻,是一個(gè)對(duì)象,用來向外提供模塊接口捂寿;
3.module口四,是一個(gè)對(duì)象,上面存儲(chǔ)了與當(dāng)前模塊相關(guān)聯(lián)的一些屬性和方法秦陋。

//定義沒有依賴的模塊
define(function(require,exports,module){
  exports.xxx = value
module.exports = value
})
//定義有依賴的模塊
define(function(require,exports,module){
  //同步引入模塊
  var module1 = require('./module1.js')
  //異步引入模塊
  require.async('./module2.js',function(m2){
  /***/
})
exports.xxx = value
}
//引入模塊
define(function(require){
  const m1 = require('./module1.js');
m1.show()
})

五UMD通用模塊規(guī)范

一種整合了CommonJS和AMD規(guī)范的方法蔓彩,希望能解決跨平臺(tái)模塊方案。
運(yùn)行原理
-UMD先判斷是否支持Node.js模塊(exports是否存在)驳概,存在則用Node.js模塊模式赤嚼。
-在判斷是否支持AMD(define是否存在)存在則使用AMD加載模塊。

(function (window, factory) {
    if (typeof exports === 'object') {  
        module.exports = factory();
    } else if (typeof define === 'function' && define.amd) {
        define(factory);
    } else {    
        window.eventUtil = factory();
    }
})(this, function () {
    //module ...
});

六顺又、總結(jié)

commonjs是同步加載的更卒,主要是在nodejs也就是服務(wù)端應(yīng)用的模塊化機(jī)制,通過Module.export導(dǎo)出聲明稚照。通過require('')加載蹂空。每個(gè)文件都是一個(gè)模塊。他有自己的作用域锐锣,文件內(nèi)的變量腌闯,屬性函數(shù)等不能被外界訪問绳瘟。node會(huì)將模塊緩存雕憔,第二次加載會(huì)直接在緩存中獲取。
AMD是異步加載的糖声。主要應(yīng)用在瀏覽器環(huán)境下斤彼,requireJS是遵循AMD規(guī)范的模塊化工具,他是通過define()定義聲明蘸泻,通過require('',function(){})加載琉苇。

es6的模塊化加載時(shí)通過export default導(dǎo)出,用import帶入悦施,可通過{}對(duì)導(dǎo)出的內(nèi)容進(jìn)行解構(gòu)并扇。

es6的模塊的運(yùn)行機(jī)制與common不一樣,js引擎對(duì)腳本靜態(tài)分析的時(shí)候抡诞,遇到模塊加載指令后會(huì)生成一個(gè)只讀引用穷蛹,等到腳本真正執(zhí)行的時(shí)候才會(huì)通過引用去模塊中獲取值土陪,在引用到執(zhí)行的過程中,模塊中的值發(fā)生了變化肴熏,導(dǎo)入的這里也會(huì)跟著變鬼雀,es6
模塊是動(dòng)態(tài)引用,并不會(huì)緩存值蛙吏。模塊里總是綁定其所在的模塊源哩。

關(guān)于模塊化,我認(rèn)為是構(gòu)建大型項(xiàng)目所必須的鸦做,讓代碼結(jié)構(gòu)更加清晰励烦,讓模塊之間的引用關(guān)系,以及具體作用功能更加清晰馁龟,方便了團(tuán)隊(duì)聯(lián)合開發(fā)崩侠。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市坷檩,隨后出現(xiàn)的幾起案子却音,更是在濱河造成了極大的恐慌,老刑警劉巖矢炼,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件系瓢,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡句灌,警方通過查閱死者的電腦和手機(jī)夷陋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胰锌,“玉大人骗绕,你說我怎么就攤上這事∽拭粒” “怎么了酬土?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)格带。 經(jīng)常有香客問我撤缴,道長(zhǎng),這世上最難降的妖魔是什么叽唱? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任屈呕,我火速辦了婚禮,結(jié)果婚禮上棺亭,老公的妹妹穿的比我還像新娘虎眨。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布嗽桩。 她就那樣靜靜地躺著钟鸵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涤躲。 梳的紋絲不亂的頭發(fā)上棺耍,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音种樱,去河邊找鬼蒙袍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛嫩挤,可吹牛的內(nèi)容都是我干的害幅。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼岂昭,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼以现!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起约啊,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤邑遏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后恰矩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體记盒,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年外傅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纪吮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡萎胰,死狀恐怖碾盟,靈堂內(nèi)的尸體忽然破棺而出或辖,到底是詐尸還是另有隱情往弓,我是刑警寧澤跟压,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布亥揖,位于F島的核電站,受9級(jí)特大地震影響桌粉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一瓷患、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧遣妥,春花似錦擅编、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)谭贪。三九已至,卻和暖如春锦担,著一層夾襖步出監(jiān)牢的瞬間俭识,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工洞渔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留套媚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓磁椒,卻偏偏與公主長(zhǎng)得像堤瘤,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子浆熔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容