node系列之modules

地址

傳送門(mén)

說(shuō)明

模塊也算是nodejs的核心了佳遣。每個(gè)js文件就是一個(gè)模塊,通過(guò)exports對(duì)外開(kāi)放自己的方法税稼。正是因?yàn)橛辛薽odule的存在身害,才能讓nodejs實(shí)現(xiàn)模塊化。

功能模塊

  • 訪問(wèn)主模塊(最開(kāi)始的調(diào)用者)
    1.js require 2.js, 2.js require 3.js澈缺。 在3.js 里面可以通過(guò)訪問(wèn) require.main來(lái)獲得1.js模塊坪创。
// 1.js
module.exports = {   
  a: 44
};
require('./2');
//3.js
console.log(require.main.exports);
// output: {a: 44}

這里需要注意的是,直接獲取的require.main指的是這個(gè)模塊姐赡,并不是module.exports對(duì)象莱预。所以想要獲取主模塊對(duì)外的屬性,可以通過(guò)require.main.exports來(lái)實(shí)現(xiàn)项滑。所以require.main指的是module而不是module.exports依沮。

  • 循環(huán)依賴(lài)
    記住一個(gè)原則: 當(dāng)require一個(gè)文件的時(shí)候,不管有沒(méi)有遇到循環(huán)依賴(lài)枪狂,你獲取到的這個(gè)模塊危喉,就是當(dāng)前的module.exports。比如
// 1.js
console.log('1 starting');
exports.a= 1;
var b = require('./2.js');
exports.b= 2;
// 2.js
console.log('2 starting');
var b = require('./2.js');
console.log(b);
// output:  {a: 1}

因?yàn)樵?.js在加載 2.js的過(guò)程中州疾,它是沒(méi)有完全執(zhí)行的(只有a屬性而沒(méi)有b屬性)辜限,所以在2.js獲取到的1.js,其實(shí)也就只有a屬性严蓖。等這些文件都完全加載完之后薄嫡,再更新require.cache氧急。在此之前,都是半成品(雖然也會(huì)寫(xiě)入緩存)毫深。

緩存機(jī)制

上面說(shuō)得有點(diǎn)亂吩坝,現(xiàn)在再來(lái)理清一下緩存的機(jī)制。在剛加載這個(gè)文件的時(shí)候哑蔫,就已經(jīng)將這個(gè)模塊放在緩存require.cache里面了钾恢,假如繼續(xù)有修改的話,會(huì)發(fā)現(xiàn)緩存也會(huì)接著變化鸳址。比如

console.log(require.cache);   // exports = {};
module.exports.a = 2;
console.log(require.cache);  // exports = {a: 2}

執(zhí)行上面這些語(yǔ)句的時(shí)候瘩蚪,可以對(duì)比一下兩次輸出,會(huì)發(fā)現(xiàn)緩存的對(duì)象已經(jīng)存在了稿黍,只是可能會(huì)接著發(fā)生變化而已疹瘦。下面有兩個(gè)問(wèn)題

  • 如果有一個(gè)模塊未被完全加載,然后同時(shí)被另外的模塊加載巡球,那豈不是加載的數(shù)據(jù)不一樣啦言沐?
    A:是的,比如上面那個(gè)循環(huán)依賴(lài)的例子

  • 加載一個(gè)模塊之后酣栈,可以通過(guò)修改它的數(shù)據(jù)來(lái)改變緩存嗎险胰,然后導(dǎo)致其他的調(diào)用者也發(fā)生變化嗎?
    A:

var a = require('./other');
console.log(require.cache);
a.aaaaa = 33333;
console.log(require.cache);

通過(guò)上面簡(jiǎn)單地例子矿筝,我們可以看出起便,是的。會(huì)改變窖维。因?yàn)樵谶@里榆综,修改的是引用指向的內(nèi)存塊,所以能直接修改铸史。

文件模塊

在很多的nodejs開(kāi)源項(xiàng)目里面鼻疮,在某個(gè)文件夾下,會(huì)有個(gè)package.json文件琳轿。其中namemain是兩個(gè)比較重要的參數(shù)判沟。前者代表這個(gè)模塊的名字;后者表示崭篡,當(dāng)被加載的時(shí)候挪哄,去哪個(gè)地方尋找入口文件。比如在example文件下的
package.json

{  
  "name": "a6666",  
  "main": "./../test.js"
}

當(dāng)require('./example')的時(shí)候媚送,發(fā)現(xiàn)有個(gè)說(shuō)明文件中燥,然后根據(jù)main查找入口文件寇甸。所以最終加載的是test.js塘偎。main`參數(shù)默認(rèn)是index.js疗涉。那么問(wèn)題來(lái)了,假如某個(gè)文件夾下有個(gè)example文件夾和同名文件example.js吟秩,會(huì)加載哪個(gè)呢咱扣?手動(dòng)試試就知道啦。我猜是加載目錄涵防。想要知道具體的原因的話闹伪,可以了解下模塊加載的順序。

加載node_modules的順序

從當(dāng)前的node_modules一直尋找壮池,找不到的話繼續(xù)在父目錄尋找偏瓤,直到找到為止,實(shí)在找不到就報(bào)錯(cuò)了椰憋。

這里有個(gè)全局模塊的概念厅克,會(huì)在環(huán)境變量中查找node_modules。不過(guò)官方并不推薦橙依,稱(chēng)之為“歷史原因”证舟,而且速度會(huì)降下來(lái)。所以建議是直接放在項(xiàng)目本地就好啦窗骑。

模塊包裝器

這是一個(gè)很重要的東西女责。因?yàn)橛羞@個(gè),才會(huì)有模塊化存在创译。每個(gè)文件其實(shí)是經(jīng)過(guò)包裝的(不然你以為那5個(gè)“全局”變量是怎么來(lái)的)

(function (exports, require, module, __filename, __dirname) {
  // Your module code actually lives in here
});

這一層我們開(kāi)發(fā)者是感知不到的抵知,因?yàn)樵谶\(yùn)行時(shí)期才會(huì)進(jìn)行包裝。所以我們能直接使用這些變量软族。有了這個(gè)東東辛藻,想要污染全局變量都難啊

module的一些屬性

  • module.children

  • module.parent
    上面這兩個(gè)屬性可以看出各個(gè)模塊的加載次序。一個(gè)模塊可以被加載多次互订,但是module.parent只有一個(gè)吱肌,隨之而來(lái)的是,一個(gè)模塊仰禽,只能是某一個(gè)模塊的children氮墨,而不能是多個(gè)。因?yàn)橥驴诘谝淮渭虞d的時(shí)候规揪,這些父子爺輩關(guān)系已經(jīng)明確下來(lái)了。無(wú)論后面怎么加載與被加載温峭,都不會(huì)發(fā)生變化猛铅。當(dāng)然,手動(dòng)修改緩存除外咯凤藏。

  • module.loaded 是否曾經(jīng)被加載過(guò)

  • module.require(id) 返回緩存里面的 module.exports對(duì)象奸忽。

  • module.id 緩存的key(一般來(lái)說(shuō)文件實(shí)際路徑)

  • module.filename 緩存模塊的文件路徑

  • module.exports 用得最多的堕伪,就是這個(gè)家伙了。不解釋了栗菜。

小結(jié)

nodejs的模塊系統(tǒng)還是設(shè)計(jì)得挺好的欠雌,尤其是模塊化。比較有意思的是模塊加載機(jī)制疙筹。上面的 傳送門(mén) 有得看富俄,我也不解釋了(其實(shí)我沒(méi)深入看過(guò),哈哈)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末而咆,一起剝皮案震驚了整個(gè)濱河市霍比,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌暴备,老刑警劉巖桂塞,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異馍驯,居然都是意外死亡阁危,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)汰瘫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)狂打,“玉大人,你說(shuō)我怎么就攤上這事混弥∨肯纾” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵蝗拿,是天一觀的道長(zhǎng)晾捏。 經(jīng)常有香客問(wèn)我,道長(zhǎng)哀托,這世上最難降的妖魔是什么惦辛? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮仓手,結(jié)果婚禮上胖齐,老公的妹妹穿的比我還像新娘。我一直安慰自己嗽冒,他們只是感情好呀伙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著添坊,像睡著了一般剿另。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,842評(píng)論 1 290
  • 那天雨女,我揣著相機(jī)與錄音谚攒,去河邊找鬼。 笑死戚篙,一個(gè)胖子當(dāng)著我的面吹牛五鲫,可吹牛的內(nèi)容都是我干的溺职。 我是一名探鬼主播岔擂,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼浪耘!你這毒婦竟也來(lái)了乱灵?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤七冲,失蹤者是張志新(化名)和其女友劉穎痛倚,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體澜躺,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蝉稳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了掘鄙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耘戚。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖操漠,靈堂內(nèi)的尸體忽然破棺而出收津,到底是詐尸還是另有隱情,我是刑警寧澤浊伙,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布撞秋,位于F島的核電站,受9級(jí)特大地震影響嚣鄙,放射性物質(zhì)發(fā)生泄漏吻贿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一哑子、第九天 我趴在偏房一處隱蔽的房頂上張望廓八。 院中可真熱鬧,春花似錦赵抢、人聲如沸剧蹂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)宠叼。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間冒冬,已是汗流浹背伸蚯。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留简烤,地道東北人剂邮。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像横侦,于是被迫代替她去往敵國(guó)和親挥萌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

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

  • topics: 1.The Node.js philosophy 2.The reactor pattern 3....
    宮若石閱讀 1,064評(píng)論 0 1
  • Node.js是目前非惩鞑啵火熱的技術(shù)引瀑,但是它的誕生經(jīng)歷卻很奇特。 眾所周知榨馁,在Netscape設(shè)計(jì)出JavaScri...
    w_zhuan閱讀 3,610評(píng)論 2 41
  • 模塊 Node 有簡(jiǎn)單的模塊加載系統(tǒng)憨栽。在 Node 里,文件和模塊是一一對(duì)應(yīng)的翼虫。下面例子里屑柔,foo.js加載同一個(gè)...
    保川閱讀 592評(píng)論 0 0
  • Node.js Stream(流) Stream 是一個(gè)抽象接口,Node 中有很多對(duì)象實(shí)現(xiàn)了這個(gè)接口珍剑。例如掸宛,對(duì)h...
    FTOLsXD閱讀 601評(píng)論 0 2
  • 小時(shí)候的興趣愛(ài)好沒(méi)想到過(guò)去了十幾年還會(huì)因?yàn)槟阕屛议_(kāi)心
    亦雪_6254閱讀 139評(píng)論 0 0