關(guān)于nodejs中module.exports和exports的關(guān)系,其實(shí)網(wǎng)上有許多文章有解釋,但看完之后還是理解得不夠深入。
經(jīng)過代碼測(cè)試之后,我才徹底明白。
因此我比較喜歡用代碼說明問題。
module.exports和exports是怎樣的存在

從代碼可以看出,在node環(huán)境中。 js文件運(yùn)行時(shí),會(huì)有一個(gè)默認(rèn)的module對(duì)象,而exports是module.exports的一個(gè)引用,當(dāng)給exports添加屬性時(shí),module.exports也跟隨改變。
而當(dāng)使用如 module.exports={a:'ddd'} 的形式定義輸出時(shí),module.exports就指向了一個(gè)新的引用,但exports仍然是原來的引用,因此是一個(gè)空對(duì)象。

用module.exports導(dǎo)出就可以了,為什么要增加一個(gè)exports?
這點(diǎn)我覺得是想寫代碼方便一點(diǎn)。
誠然,我們可以把所有內(nèi)容放到一個(gè)obj中,用一個(gè)module.exports=obj就可以導(dǎo)出。但有時(shí)我們希望書寫更加自由??梢悦繉懸粋€(gè)方法輸出一個(gè)。不至于都擠在一堆。
例如:

但是這樣子會(huì)寫很多個(gè)module.exports,不如再定義一個(gè)var exports=module.exports, 于是就有了exports的存在。
為什么模塊定義要寫exports=module.exports=xxx?
當(dāng)使用module.exports=xxx定義之后,module.exports與exports就指向了不同的對(duì)象。但最終模塊被引入時(shí),使用的是module.exports的內(nèi)容。
例如:

這里定義了一個(gè)b.js,其中引入a.js模塊,引入后a.js模塊定義的exports.b并沒有導(dǎo)出,原因是exports與module.exports指向了不同對(duì)象。
但如果使用exports=module.exports=xxx ,使exports和module.exports重新統(tǒng)一指向,最后exports.b就會(huì)被導(dǎo)出。
但要注意的是。xxx必須是一個(gè)能添加屬性的對(duì)象,可以是object,可以是function,甚至可以是數(shù)組,但絕不能是基本類型

總結(jié)
之所以要在module.exports之外再定義一個(gè)exports,是因?yàn)橄M麑懘a時(shí)導(dǎo)出內(nèi)容更靈活。
而由于存在module.exports賦值后指向變更的問題,使module.exports和exports 兩種形式混用時(shí)存在漏洞。用exports=module.exports=xxx可以避免此問題。
如果模塊中只用exports或只用module.exports導(dǎo)出對(duì)象,其實(shí)是沒有必要這樣寫的。
當(dāng)然,如果要統(tǒng)一作為代碼規(guī)范,還是推薦這種嚴(yán)謹(jǐn)?shù)膶懛ā?/p>