咱們知道NodeJS遵循
CommonJS
的規範,使用require
關鍵字來加載模塊,使用exports
和module.exports
來導出模塊,那麼這兩個導出又有什麼關係或者區別呢?html
其實,在node執行一個文件時,會給這個文件內生成一個 exports
對象和一個 module
對象,而這個module
對象又有一個屬性叫作 exports
node
新建一個index.js文件 執行 node index.js
命令api
console.log(exports)
console.log(module)
複製代碼
能夠看出控制檯的輸出結果以下: bash
咱們再來看看exports
和
module.exports
有什麼關係呢? 咱們在index.js 文件中添加一句代碼
console.log(exports === module.exports)
複製代碼
會發現結果是 true
這說明,文件開始執行的時候,它們是指向同一塊內存區域的app
graph LR;
A[exports] ; B[內存:xxx]; C[module.exports]
A-->B
C-->B
複製代碼
當文件執行完畢的時候,只有module.exports
變量被返回了,以便後續被其餘模塊 require
引用,爲了證實這個觀點,咱們能夠新建一個文件 index2.js 進行測試 index2.js測試
exports.a = 1
複製代碼
而後在 index3.js 中引用ui
const module2 = require('./index2')
console.log(module2)
複製代碼
控制檯輸出: { a: 1 }
而後咱們在 index2.js 中添加代碼:spa
exports.a = 1
module.exports = {
b:2
}
複製代碼
在這裏同時使用兩個導出方法,查看控制檯輸出結果爲 { b: 2 }
此時,咱們繼續在 index2.js 文件中添加code
console.log(exports === module.exports)
複製代碼
結果爲false
,此時的 exports
和 module.exports
已經不是指向同一塊內存地址了,由於前面的代碼裏面,咱們使用了cdn
module.exports = {
b:2
}
複製代碼
這致使了 module.exports
從新指向了新的內存地址, 可是當咱們執行 node index3.js
查看index3.js 的運行結果時,看到的是 {b:2}
而不是 {a:1}
證實了咱們上面的觀點: 只有module.exports
變量被返回了 所以,初始化的狀態,咱們能夠用以下代碼來幫助理解:
var module = {
exports:{}
}
var exports = module.exports
複製代碼
而最終的導出結果是 module.exports
這個對象. 到了這裏,可能有人又會有疑問,爲啥以前不少的模塊都是須要引入才能使用,可是exports
和module.exports
咱們沒有引用卻能直接使用? 這個問題的答案咱們能夠從Node的官方文檔中找到答案,
(function(exports,require,module,__filename,__dirname){
...
})
複製代碼
在進行了頭尾封裝後,各模塊之間進行了做用域的隔離,避免了污染全局變量,經過頭尾封裝,實現了
總結:
exports
對象是 module
對象的一個屬性,在初始時 module.exports
和 exports
指向同一塊內存區域module.exports
, exports
只是對它的引用,在不改變exports
內存的狀況下,修改exports
的值能夠改變 module.exports
的值module.exports
,以避免由於各類賦值致使的混亂