Node.js遵循CommonJS規範的模塊機制,一個JS文件即被視爲一個獨立的模塊。在模塊內部能夠經過2種方式導出模塊:javascript
module.exports是一個對象引用,這個對象具備如下特徵:java
exports也是一個對象引用,它與module.exports默認指向同一個對象bash
console.log(module.exports === exports); // true
複製代碼
因此若是咱們只是向module.exports(或exports)追加須要導出的內容時,採用哪一種方式均可以,由於二者始終指向同一個對象ui
module.exports.a = 1;
console.log(module.exports); // { a: 1 }
console.log(exports); // { a: 1 }
exports.b = 2;
console.log(module.exports); // { a: 1, b: 2 }
console.log(exports); // { a: 1, b: 2 }
複製代碼
但若是給module.exports(或exports)從新賦值,那麼就會出現一些意想不到的效果。假設咱們使用以下的方式導出模塊spa
// foo.js
module.exports = {
a: 1
}
exports.b = 2;
複製代碼
// main.js
var foo = require('./foo');
console.log(foo); // { a: 1 },導出的對象並不包含b
複製代碼
出現上面結果的緣由是:module.exports
在被’=’賦值時,其實是新生成了一個{a: 1}
對象,而且斷開module.exports
與默認對象{}
的引用,從而指向{a: 1}
這個新生成的對象;然而exports
此時仍是指向默認對象{}
,exports.b = 2;
其實是向這個默認對象添加了b
,而不是module.exports
所指的那個對象;而且Node模塊最終只會導出module.exports所指向的那個對象(或值),因此就出現了上面的結果。code
歸納一句話就是:給模塊對象的從新複製致使module.exports與exports分別指向了不一樣的對象對象
‘最好的證實就是用代碼演示’,因此咱們代碼證實一下上面的分析ip
// foo.js
module.exports = {
a: 1
}
exports.b = 2;
console.log(module.exports === exports); // false
console.log(module.exports); // { a: 1 }
console.log(exports); // { b: 2 }
複製代碼
// main.js
var foo = require('./foo');
console.log(foo); // { a: 1 }
複製代碼
那麼是否有辦法修補上面的問題呢?答案是:有的,問題的關鍵是:module.exports與exports指向了不一樣的對象,那麼咱們就將它們指回同一個對象get
// foo.js
module.exports = {
a: 1
}
console.log(module.exports === exports); // false
exports = module.exports;
exports.b = 2;
console.log(module.exports === exports); // true
console.log(module.exports); // { a: 1, b: 2 }
console.log(exports); // { a: 1, b: 2 }
複製代碼
因此,導出模塊時咱們最好採用以下形式:string
exports = module.exports = {
a: 1
}
console.log(module.exports === exports); // true
console.log(module.exports); // { a: 1 }
console.log(exports); // { a: 1 }
複製代碼
以上就是對module.exports與exports二者關係的淺顯分析,但願對你們有所幫助,若有錯誤,歡迎指正~