commonjs簡(jiǎn)介

學(xué)習(xí)一門技術(shù)孩等,基礎(chǔ)是關(guān)鍵艾君,比如想學(xué)react或redux,那就得有node和webpack的基礎(chǔ)肄方;學(xué)習(xí)webpack冰垄,知道commonjs規(guī)范,理解起來才會(huì)更快 权她。所謂萬丈高樓平地起虹茶,基礎(chǔ)打牢了,理解知識(shí)點(diǎn)才會(huì)更透徹隅要,后期提升才會(huì)更快蝴罪。

nodejs和commonjs區(qū)別?

commonjs是規(guī)范步清,nodejs是這種規(guī)范的實(shí)現(xiàn)要门。
commonjs還在不斷的發(fā)展,還會(huì)有新的東西往里添加廓啊。

CommonJs有很多實(shí)現(xiàn)欢搜,其中不乏大名鼎鼎的項(xiàng)目,比如說Apache的CouchDBnode.js
這些項(xiàng)目大部分只實(shí)現(xiàn)CommonJs的部分規(guī)范谴轮。

CommonJs概述

每個(gè)文件就一個(gè)模塊狂巢,有自己的作用域。在一個(gè)文件里面定義的變量书聚、函數(shù)唧领、類,都是私有的雌续,對(duì)其他文件不可見斩个。

私有作用域不會(huì)污染全局作用域。
模塊可加載多次驯杜,只會(huì)在第一次加載時(shí)運(yùn)行一次受啥,然后結(jié)果會(huì)被緩存起來,以后在使用鸽心,就直接讀取緩存結(jié)果滚局。想要讓模塊再次運(yùn)行,必須清除緩存
模塊加載順序是按照其在代碼中出現(xiàn)的順序

基本使用

1顽频、輸出:module對(duì)象藤肢。
使用module.exports輸出一個(gè)變量或函數(shù),也可以使用exports輸出

var x = 5;
var addX = function (value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;

module是可以省略的糯景。
2嘁圈、module對(duì)象
node內(nèi)部提供一個(gè)module構(gòu)建函數(shù)。每個(gè)模塊內(nèi)部蟀淮,都有一個(gè)module對(duì)象最住,代表當(dāng)前模塊,他有一些自身屬性

module.id 模塊的識(shí)別符怠惶,通常是帶有絕對(duì)路徑的模塊文件名涨缚。
module.filename 模塊的文件名,帶有絕對(duì)路徑策治。
module.loaded 返回一個(gè)布爾值脓魏,表示模塊是否已經(jīng)完成加載。
module.parent 返回一個(gè)對(duì)象览妖,表示調(diào)用該模塊的模塊轧拄。
module.children 返回一個(gè)數(shù)組,表示該模塊要用到的其他模塊讽膏。
module.exports 表示模塊對(duì)外輸出的值檩电。

3、exports變量
node為么每個(gè)模塊提供一個(gè)exports變量府树,指向module.exports

exports.area = function(r){console.log(r)}
這個(gè)是ok的俐末。

exports = function(r){console.log(r)}
這個(gè)寫法無效,因?yàn)楦淖兞烁淖兞薳xports的指向

如果一個(gè)文件中 module.exports 被重新賦值奄侠,該文件中其他exports出去的變量(屬性)也是無效的晴楔。

說說加載

上面說了輸出(module.exoprts、exports),接下來說說載入巷挥。
node采用CommonJS規(guī)范。內(nèi)置require命令用于加載模塊:var foo = require("filename")

加載規(guī)則

說說require內(nèi)部處理流程
1闷盔、在加載前,檢查是否有緩存(module._cache)
2旅急、如果緩存之中沒有逢勾,就創(chuàng)建一個(gè)新的module實(shí)例
3、將他緩存起來
4藐吮、使用module.load()加載指定模塊文件溺拱;讀取文件內(nèi)容之后,使用module.compile()執(zhí)行文件代碼
5谣辞、如果加載/解析過程報(bào)錯(cuò)迫摔,就從緩存刪除該模塊
6、返回該模塊的module.exports

第一步是加載文件的規(guī)則
一般后綴默認(rèn)為.js

路徑分三種情況
1泥从、('/home/app.js') -->絕對(duì)路徑
2句占、('./home/app.js') -->相對(duì)路徑 (當(dāng)前路徑下的home文件夾下的appjs文件)
3、('react') --> 沒有 以 ‘./ 和 /’開頭的路徑歉闰,則表示加載的一個(gè)默認(rèn)提供的核心模塊辖众,會(huì)去node_modules文件夾下找或node的系統(tǒng)安裝目錄中找

如果指定的文件沒有發(fā)現(xiàn),node會(huì)嘗試為文件名添加.js .json .node后綴和敬,再搜索凹炸。.js文件會(huì)以文本格式的js腳本文件解析,.json文件會(huì)以JSON格式的文本文件解析昼弟,.node文件會(huì)以編譯后的二進(jìn)制文件解析啤它。

模塊緩存
第一次加載某個(gè)模塊,node會(huì)緩存該模塊舱痘,以后再次加載會(huì)直接從緩存中取出該模塊的module.exports屬性
刪除執(zhí)行模塊
delete require.cache[moduleName]

AMD規(guī)范與CommonJS的區(qū)別

CommonJS加載模塊是同步的变骡,加載完才執(zhí)行后續(xù)操作;
AMD是異步加載模塊芭逝,允許指定回調(diào)函數(shù)塌碌。
nodejs用于服務(wù)器端,代碼文件一般都在本地硬盤旬盯,加載比較快台妆,適合使用CommonJS,而瀏覽器環(huán)境胖翰,要從服務(wù)器加載模塊接剩,比較慢,所以瀏覽器一般采用AMD規(guī)范萨咳。

為什么會(huì)有規(guī)范懊缺?

回答這個(gè)問題之前得知道為什么要有模塊?

因?yàn)橛辛四K,我們就可以很方便的使用別人的代碼培他,想要什么功能鹃两,就加載什么模塊遗座,這樣帶來了一個(gè)問題大家得按照相應(yīng)的方式編寫模塊,不然每個(gè)人寫自己風(fēng)格的代碼俊扳,豈不是亂套了员萍。

所有才有了CommonJS、AMD拣度、CMD這些規(guī)范!

再說說AMD規(guī)范

全稱:異步模塊定義

誕生背景:基于commonJS規(guī)范的nodeJS出來以后螃壤,服務(wù)端的模塊概念已經(jīng)形成抗果,很自然地,大家就想要客戶端模塊奸晴。而且最好兩者能夠兼容冤馏,一個(gè)模塊不用修改,在服務(wù)器和瀏覽器都可以運(yùn)行寄啼。但是逮光,由于一個(gè)重大的局限,使得CommonJS規(guī)范不適用于瀏覽器環(huán)境墩划。
同步加載對(duì)服務(wù)器端不是一個(gè)問題涕刚,因?yàn)樗械哪K都存放在本地硬盤,可以同步加載完成乙帮,等待時(shí)間就是硬盤的讀取時(shí)間杜漠。但是,對(duì)于瀏覽器察净,這卻是一個(gè)大問題驾茴,因?yàn)槟K都放在服務(wù)器端,等待時(shí)間取決于網(wǎng)速的快慢氢卡,可能要等很長(zhǎng)時(shí)間锈至,瀏覽器處于"假死"狀態(tài)。
因此译秦,瀏覽器端的模塊峡捡,不能采用"同步加載"(synchronous),只能采用"異步加載"(asynchronous)诀浪。這就是AMD規(guī)范誕生的背景棋返。

AMD實(shí)現(xiàn)庫有 require.jscurl.js
requirejs主要解決兩個(gè)問題:
1雷猪、實(shí)現(xiàn)js文件的異步加載睛竣,避免頁面因?yàn)閖s文件加載失去響應(yīng)
2、管理模塊之間的依賴性求摇,便于代碼的編寫和維護(hù)

AMD模塊的寫法

模塊必須使用define函數(shù)來定義射沟。如果一個(gè)模塊不依賴其他模塊殊者,那么可以直接定義在define()函數(shù)之中。
例子:

   // 沒有依賴其他模塊
   //math.js
   define(function (){
    var add = function (x,y){
      return x+y;
    };
    return {
      add: add
    };
  });
   // 加載方法(這是沒有)
    require(['math'], function (math){
    alert(math.add(1,1));
   });

  //如果依賴其他模塊
  define(['myLib'], function(myLib){
    function foo(){
      myLib.doSomething();
    }
    return {
      foo : foo
    };
 });
// 會(huì)先加載myLib模塊

還可以加載非規(guī)范的模塊
使用require.config方法验夯,定義他們的一些特征
例子:

   // underscore和backbone這兩個(gè)庫猖吴,都沒有采用AMD規(guī)范編寫。如果要加載它們的話挥转,必須先定義它們的特征海蔽。
    require.config({
    shim: {

      'underscore':{
        exports: '_'
      },
      'backbone': {
        deps: ['underscore', 'jquery'],
        exports: 'Backbone'
      }
    }
  });

另外還有CMD,玉伯寫的seajs绑谣,就是遵循他提出的CMD規(guī)范党窜。

總結(jié)

  • 為什么要有規(guī)范?
    因?yàn)橐K化借宵。

  • 為什么要模塊化幌衣?
    因?yàn)楝F(xiàn)在項(xiàng)目越來越大,按照功能劃分壤玫,使用的時(shí)候直接加載相應(yīng)的模塊即可豁护,利于維護(hù)和開發(fā)。比如nodejs都可以做服務(wù)器端語言了欲间,將來項(xiàng)目肯定會(huì)越來越大楚里,越來越復(fù)雜(個(gè)人認(rèn)為:node將來會(huì)向java、Python這個(gè)方向發(fā)展的)括改。項(xiàng)目劃分清晰明了

  • 為什么現(xiàn)在有那么多規(guī)范腻豌?(CommonJS、AMD嘱能、CMD)
    因?yàn)椴煌?guī)范適用于不同的場(chǎng)景吝梅。
    CommonJS是同步加載,很快能得到結(jié)果的可以使用這個(gè)方式惹骂。比如:node加載文件時(shí)是在本地硬盤加載的苏携,肯定快。
    AMD对粪、CMD是異步加載右冻,獲取結(jié)果比較慢的的情況可以使用這種方式,因?yàn)樗梢栽O(shè)置回調(diào)著拭,什么時(shí)候加載完成纱扭,什么時(shí)候執(zhí)行對(duì)調(diào)。比如:瀏覽器加載服務(wù)器的數(shù)據(jù)儡遮,這個(gè)受網(wǎng)絡(luò)環(huán)境影響很大乳蛾,不能一直等服務(wù)器返回結(jié)果。所以可以給個(gè)回調(diào)方法,什么時(shí)候有結(jié)果了肃叶,走回調(diào)即可蹂随。

第一次寫這么長(zhǎng)的文章,肯定有很多值得商榷的地方因惭,以后好好努力

參考文獻(xiàn):
什么是CommonJS? - 依水間 - 博客園
js模塊化編程之徹底弄懂CommonJS和AMD/CMD!
CommonJS規(guī)范 -- JavaScript 標(biāo)準(zhǔn)參考教程(alpha)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末岳锁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蹦魔,更是在濱河造成了極大的恐慌激率,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勿决,死亡現(xiàn)場(chǎng)離奇詭異柱搜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)剥险,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宪肖,“玉大人表制,你說我怎么就攤上這事】厍” “怎么了么介?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蜕衡。 經(jīng)常有香客問我壤短,道長(zhǎng),這世上最難降的妖魔是什么慨仿? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任久脯,我火速辦了婚禮,結(jié)果婚禮上镰吆,老公的妹妹穿的比我還像新娘帘撰。我一直安慰自己,他們只是感情好万皿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布摧找。 她就那樣靜靜地躺著,像睡著了一般牢硅。 火紅的嫁衣襯著肌膚如雪蹬耘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天减余,我揣著相機(jī)與錄音综苔,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛休里,可吹牛的內(nèi)容都是我干的蛆挫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼妙黍,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼悴侵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拭嫁,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤可免,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后做粤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浇借,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年怕品,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了妇垢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡肉康,死狀恐怖闯估,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吼和,我是刑警寧澤涨薪,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站炫乓,受9級(jí)特大地震影響刚夺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜末捣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一侠姑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧箩做,春花似錦结借、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至圃酵,卻和暖如春柳畔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背郭赐。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工薪韩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留确沸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓俘陷,卻偏偏與公主長(zhǎng)得像罗捎,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拉盾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

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