關於Node.js中的exports和module.exports,不少時候都比較容易讓人混淆,弄不清楚二者間的區別。那麼咱們就從頭開始理清這二者之間的關係。javascript
在開發Node.js應用的時候,不少模塊都是須要引入才能使用,可是爲何exports和module.exports咱們沒有引用卻能夠直接使用呢?java
事實上,Node.js應用在編譯的過程當中會對JavaScript文件的內容進行頭尾的封裝。例如:ui
// hello.js
const hello = function () {
console.log('Hello world');
}
module.exports = {
hello
}
// 頭尾封裝後的js代碼
(function (exports, require, module, __filename, __dirname) {
const hello = function () {
console.log('Hello world');
}
module.exports = {
hello
}
})
複製代碼
在進行了頭尾封裝以後,各個模塊之間進行了做用域隔離,避免了污染全局變量,同時能夠使每一個模塊在不引入這些變量的狀況下能夠使用它們。這些變量依次爲當前模塊的exports屬性、require()方法、當前模塊自身(module)、在文件系統中的完整路徑、文件目錄。spa
按照Node.js的解釋,exports是module對象的一個屬性,那麼exports和module.exports應該是等價的。的確如初,初始化的exports和module.exports變量的值均爲{},代碼驗證:code
// hello.js
const hello = function () {
console.log('Hello world');
}
console.log('初始值==========');
console.log(exports);
console.log(module.exports);
module.exports = {
hello
}
// 輸出結果
初始值==========
{}
{}
複製代碼
能夠發現,module對象的exports屬性和exports均指向一個空對象{},那麼在導出對象的時候使用exports和module.exports有什麼區別呢?對象
咱們在使用require()方法引入模塊的時候,實際上是引入了module.exports對象, exports只是module對象的exports的一個引用,咱們能夠經過修改exports所指向對象的值來協助修改module.exports的值。ip
const hello = function () {
console.log('Hello world');
}
exports.hello = {
hello
}
console.log('修改值==========');
console.log(exports);
console.log(module.exports);
// 輸出結果
修改值==========
{ hello: { hello: [Function: hello] } }
{ hello: { hello: [Function: hello] } }
複製代碼
因爲exports和module.exports指向同一塊內存區域,因此咱們修改exports對象的數據,那麼module.exports也會隨之改變。內存
// hello.js
const hello = function () {
console.log('Hello world');
}
module.exports = {
hello
}
console.log('修改值==========');
console.log(exports);
console.log(module.exports);
// 輸出結果
修改值==========
{}
{ hello: [Function: hello] }
複製代碼
你會發現修改後的exports依然是{},而module.exports的值已經改變,這是因爲當你給module.exports是直接等於一個新的對象,那麼其將指向一塊新的內存區域,而此時exports指向的仍然是以前的內存區域,因此兩者的值會不同,可是此時你在其餘文件內引入hello.js文件,仍然能夠調用hello()方法,這也說明了導出的是module.exports而不是exports。作用域
// hello.js
const hello = function () {
console.log('Hello world');
}
exports = {
hello
}
console.log('修改值==========');
console.log(exports);
console.log(module.exports);
// 輸出結果
修改值==========
{ hello: [Function: hello] }
{}
複製代碼
使用這種方法導出在其餘文件調用hello方法即會報錯,由於該文件模塊導出的對象爲空,固然也不可能有hello()方法,這種問題的緣由一樣是指向的內存區域發生變化所致使的。開發