前端模塊化

在學(xué)node.js, 實(shí)際上就是基于common.js開(kāi)發(fā)的亚隅,所以了解了一下模塊化開(kāi)發(fā)昧绣。

JS的模塊化初衷和所有語(yǔ)言的模塊化都是一致的珊泳,就是規(guī)范化開(kāi)發(fā)弥雹。

1.最早期的時(shí)候就是原生的js從上到下代碼編寫執(zhí)行缺猛,

    function fun1(){ //... }
    function fun2(){ //... }

所有的函數(shù)和變量都直接放入相應(yīng)的js文件中缨叫。導(dǎo)致的問(wèn)題就是全局對(duì)象Global被污染椭符,函數(shù)命名沖突。同時(shí)在js文件之間有所依賴時(shí)耻姥,還要保證文件引入的順序销钝,文件之間的依賴關(guān)系不好管理。

2.為了解決上面的問(wèn)題琐簇,采用了使用對(duì)象封裝的模式蒸健。

    var module1 = {
        property1 : 1,
        property2 : 2,
        fun1 : function(){},
        fun2: function(){}
    }
    obj.fun1();

好處是減少了對(duì)全局對(duì)象的污染,而新的問(wèn)題是對(duì)象類型的不安全婉商,在外部可以對(duì)其內(nèi)部進(jìn)行修改似忧。

3.而采用匿名閉包就可以達(dá)到隱藏其內(nèi)部細(xì)節(jié)的功能。

var module1 =( function () {
    var property1 = 1;
    var property2 = 2;
    function fun1(){};
    function fun2(){};
    return { fun1: fun1, fun2: fun2};
}) ();
module1.fun1();
module1.property1 ; // undefined

4.而考慮到依賴丈秩,一種比較典型的方法是JQuery封裝風(fēng)格盯捌。

(function(window){
  //代碼
  window.jQuery = window.$ = jQuery;
    //通過(guò)給window添加屬性而暴漏到全局
})(window);

通過(guò)匿名函數(shù)包裝代碼,所依賴的外部變量傳給這個(gè)函數(shù)癣籽,在函數(shù)內(nèi)部可以使用這些依賴挽唉,然后在函數(shù)的最后把模塊自身暴漏給window。
如果需要添加擴(kuò)展筷狼,則可以作為jQuery的插件瓶籽,把它掛載到$上。
這種風(fēng)格雖然靈活了些埂材,但并未解決根本問(wèn)題:所需依賴還是得外部提前提供塑顺、還是增加了全局變量。

5.而最后一個(gè)問(wèn)題俏险,文件的加載严拒。 過(guò)多的<script>標(biāo)簽引入文件導(dǎo)致請(qǐng)求過(guò)多,加載順序的固定竖独,平行加載裤唠,導(dǎo)致依賴之間的模糊。所以之后出現(xiàn)了LAB.js這種script loader 還有 module loader YUI3等莹痢。實(shí)際上因?yàn)闉g覽器端任務(wù)量較小的緣故种蘸,各種復(fù)雜的JS邏輯也可以執(zhí)行下去。但是進(jìn)入到了服務(wù)器端以后竞膳,更迫切的需要模塊化的存在航瞭。

1.CommonJS規(guī)范

CommonJS是服務(wù)器端模塊的規(guī)范,Node.js采用了這個(gè)規(guī)范坦辟。Node.JS首先采用了js模塊化的概念刊侯。
根據(jù)CommonJS規(guī)范,一個(gè)單獨(dú)的文件就是一個(gè)模塊锉走。每一個(gè)模塊都是一個(gè)單獨(dú)的作用域滨彻,也就是說(shuō)藕届,在該模塊內(nèi)部定義的變量,無(wú)法被其他模塊讀取疮绷,除非定義為global對(duì)象的屬性翰舌。
輸出模塊變量的最好方法是使用module.exports對(duì)象。

var i = 1;
var max = 30;
module.exports = function () {
  for (i -= 1; i++ < max; ) {
    console.log(i);
  }
max *= 1.1;
};

上面代碼通過(guò)module.exports對(duì)象冬骚,定義了一個(gè)函數(shù)椅贱,該函數(shù)就是模塊外部與內(nèi)部通信的橋梁。
加載模塊使用require方法只冻,該方法讀取一個(gè)文件并執(zhí)行庇麦,最后返回文件內(nèi)部的module.exports對(duì)象。

2.AMD

AMD 即Asynchronous Module Definition喜德,中文名是異步模塊定義的意思山橄。它是一個(gè)在瀏覽器端模塊化開(kāi)發(fā)的規(guī)范。
模塊將被異步加載舍悯,模塊加載不影響后面語(yǔ)句的運(yùn)行航棱。所有依賴某些模塊的語(yǔ)句均放置在回調(diào)函數(shù)中。
由于不是JavaScript原生支持萌衬,使用AMD規(guī)范進(jìn)行頁(yè)面開(kāi)發(fā)需要用到對(duì)應(yīng)的庫(kù)函數(shù)饮醇,也就是大名鼎鼎RequireJS,實(shí)際上AMD 是 RequireJS 在推廣過(guò)程中對(duì)模塊定義的規(guī)范化的產(chǎn)出
requireJS主要解決兩個(gè)問(wèn)題
1.多個(gè)js文件可能有依賴關(guān)系秕豫,被依賴的文件需要早于依賴它的文件加載到瀏覽器
2.js加載的時(shí)候?yàn)g覽器會(huì)停止頁(yè)面渲染朴艰,加載文件越多,頁(yè)面失去響應(yīng)時(shí)間越長(zhǎng)
看一個(gè)使用requireJS的例子

    // 定義模塊 myModule.js
define(['dependency'], function(){
    var name = 'Byron';
    function printName(){
        console.log(name);
    }
    return {
        printName: printName
    };
});
// 加載模塊
require(['myModule'], function (my){
    my.printName();
});

requireJS定義了一個(gè)函數(shù) define混移,它是全局變量祠墅,用來(lái)定義模塊

define(id?, dependencies?, factory);

1.id:可選參數(shù),用來(lái)定義模塊的標(biāo)識(shí)歌径,如果沒(méi)有提供該參數(shù)毁嗦,腳本文件名(去掉拓展名)
2.dependencies:是一個(gè)當(dāng)前模塊依賴的模塊名稱數(shù)組
3.factory:工廠方法,模塊初始化要執(zhí)行的函數(shù)或?qū)ο蠡仡酢H绻麨楹瘮?shù)金矛,它應(yīng)該只被執(zhí)行一次。如果是對(duì)象勺届,此對(duì)象應(yīng)該為模塊的輸出值

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
  exports.verb = function() {
    return beta.verb();
  //Or:
    return require("beta").verb();
}});

在頁(yè)面上使用require函數(shù)加載模塊

`require([dependencies], function(){});`

require()函數(shù)接受兩個(gè)參數(shù)
1.第一個(gè)參數(shù)是一個(gè)數(shù)組,表示所依賴的模塊
2.第二個(gè)參數(shù)是一個(gè)回調(diào)函數(shù)娶耍,當(dāng)前面指定的模塊都加載成功后免姿,它將被調(diào)用。加載的模塊會(huì)以參數(shù)形式傳入該函數(shù)榕酒,從而在回調(diào)函數(shù)內(nèi)部就可以使用這些模塊
require()函數(shù)在加載依賴的函數(shù)的時(shí)候是異步加載的胚膊,這樣瀏覽器不會(huì)失去響應(yīng)故俐,它指定的回調(diào)函數(shù),只有前面的模塊都加載成功后紊婉,才會(huì)運(yùn)行药版,解決了依賴性的問(wèn)題。

3.CMD

CMD 即Common Module Definition通用模塊定義喻犁,CMD規(guī)范是國(guó)內(nèi)發(fā)展出來(lái)的槽片,就像AMD有個(gè)requireJS,CMD有個(gè)瀏覽器的實(shí)現(xiàn)SeaJS肢础,SeaJS要解決的問(wèn)題和requireJS一樣还栓,只不過(guò)在模塊定義方式和模塊加載(可以說(shuō)運(yùn)行、解析)時(shí)機(jī)上有所不同传轰。實(shí)際上本身Seajs就是通過(guò)學(xué)習(xí)并通過(guò)其自己的習(xí)慣改良成的剩盒。
在 CMD 規(guī)范中,一個(gè)模塊就是一個(gè)文件慨蛙。代碼的書寫格式如下:

`define(factory);`

factory 為函數(shù)時(shí)辽聊,表示是模塊的構(gòu)造方法。執(zhí)行該構(gòu)造方法期贫,可以得到模塊向外提供的接口跟匆。factory 方法在執(zhí)行時(shí),默認(rèn)會(huì)傳入三個(gè)參數(shù):require唯灵、exports 和 module:

define(function(require, exports, module) {
// 模塊代碼
});

4.AMD與CMD的區(qū)別

所有的資料都會(huì)告訴你區(qū)別是CMD 推崇依賴就近贾铝,AMD 推崇依賴前置。實(shí)際上依賴就近的含義就是隨用隨require埠帕,而依賴前置的意思就是這一段define需要什么全部在一開(kāi)始的地方require完畢垢揩。

// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
//...
var b = require('./b') // 依賴可以就近書寫
b.doSomething()
// ...
})
// AMD 默認(rèn)推薦的是
define(['./a', './b'], function(a, b) { // 依賴必須一開(kāi)始就寫好
a.doSomething()
// ...
b.doSomething()
//...
})

但兩者都是異步操作的。

5.ES6模塊標(biāo)準(zhǔn)
實(shí)際上模塊化已經(jīng)開(kāi)始納入ES標(biāo)準(zhǔn)了敛瓷, 相應(yīng)的ES Module部分才是建議仔細(xì)學(xué)習(xí)的地方叁巨。以后應(yīng)該會(huì)向此靠攏的。

參考:
http://www.cnblogs.com/dolphinX/p/4381855.html
https://segmentfault.com/a/1190000000733959#articleHeader1
http://www.cnblogs.com/lvdabao/p/js-modules-develop.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末呐籽,一起剝皮案震驚了整個(gè)濱河市锋勺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌狡蝶,老刑警劉巖庶橱,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異贪惹,居然都是意外死亡苏章,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)枫绅,“玉大人泉孩,你說(shuō)我怎么就攤上這事〔⒘埽” “怎么了寓搬?”我有些...
    開(kāi)封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)县耽。 經(jīng)常有香客問(wèn)我句喷,道長(zhǎng),這世上最難降的妖魔是什么酬诀? 我笑而不...
    開(kāi)封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任脏嚷,我火速辦了婚禮,結(jié)果婚禮上瞒御,老公的妹妹穿的比我還像新娘父叙。我一直安慰自己,他們只是感情好肴裙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布趾唱。 她就那樣靜靜地躺著,像睡著了一般蜻懦。 火紅的嫁衣襯著肌膚如雪甜癞。 梳的紋絲不亂的頭發(fā)上宛乃,一...
    開(kāi)封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天悠咱,我揣著相機(jī)與錄音,去河邊找鬼征炼。 笑死析既,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的谆奥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼酸些,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼宰译!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起魄懂,我...
    開(kāi)封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎市栗,沒(méi)想到半個(gè)月后肋坚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年智厌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盲赊。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铣鹏,死狀恐怖哀蘑,靈堂內(nèi)的尸體忽然破棺而出诚卸,到底是詐尸還是另有隱情,我是刑警寧澤绘迁,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布合溺,位于F島的核電站缀台,受9級(jí)特大地震影響棠赛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜膛腐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一睛约、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧哲身,春花似錦辩涝、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)脯丝。三九已至商膊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巾钉,已是汗流浹背翘狱。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留砰苍,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓赚导,卻偏偏與公主長(zhǎng)得像茬缩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子吼旧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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