只要是在nodejs中寫自己的文件模塊就少不了會遇到module.exports和exports的使用,看別人的代碼大多都會使用“module.exports=exports=<對象/函數等>”怪異的串聯用法,一問原因,貌似都是雲裏霧裏,如此寫法更像是保守的防止性寫法。
這種問題除了看源代碼外,只能寫點代碼進行求證。
寫了兩個模塊文件,provider.js產生任意類型的對象, customer.js返回並輸出provider對象。
第一種情況:
provider.js,直接在exports上設置任意類型的對象。
複製代碼
exports = {name:'kxh'}
/*exports = function(){
console.log('kxh');
};
exports = 'kxh';*/
console.log('*******provider-module***********');
console.log(module);
console.log('*******provider-exports***********');
console.log(exports);
複製代碼
customer.js
var p = require('./provider');
console.log('*******customer-result***********');
console.log(p);
執行customer.js結果:
複製代碼
*******provider-module***********
{ id: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\provider.js',
exports: {},
parent:
{ id: '.',
exports: {},
parent: null,
filename: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\customer.js',
loaded: false,
children: [ [Circular] ],
paths:
[ 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\node_modules',
'D:\\ProgramDemos\\Web\\nodejs\\node_modules',
'D:\\ProgramDemos\\Web\\node_modules',
'D:\\ProgramDemos\\node_modules',
'D:\\node_modules' ] },
filename: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\provider.js',
loaded: false,
children: [],
paths:
[ 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\node_modules',
'D:\\ProgramDemos\\Web\\nodejs\\node_modules',
'D:\\ProgramDemos\\Web\\node_modules',
'D:\\ProgramDemos\\node_modules',
'D:\\node_modules' ] }
*******provider-exports***********
{ name: 'kxh' }
*******customer-result***********
{}
複製代碼
從結果看,直接向exports上設置任意類型的對象都不會被require返回給調用模塊。require返回的是module.exports的空對象。
第二種情況:
provider.js,爲exports設置任意類型的屬性。
複製代碼
exports.name = {firstName:'xh', lastName:'k'};
//exports.name = "kxh";
/*exports.printName = function(){
console.log("kxh");
};*/
console.log('*******provider-module***********');
console.log(module);
console.log('*******provider-exports***********');
console.log(exports);
複製代碼
customer.js不變。
執行customer.js結果:
複製代碼
*******provider-module***********
{ id: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\provider.js',
exports: { name: { firstName: 'xh', lastName: 'k' } },
parent:
{ id: '.',
exports: {},
parent: null,
filename: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\customer.js',
loaded: false,
children: [ [Circular] ],
paths:
[ 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\node_modules',
'D:\\ProgramDemos\\Web\\nodejs\\node_modules',
'D:\\ProgramDemos\\Web\\node_modules',
'D:\\ProgramDemos\\node_modules',
'D:\\node_modules' ] },
filename: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\provider.js',
loaded: false,
children: [],
paths:
[ 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\node_modules',
'D:\\ProgramDemos\\Web\\nodejs\\node_modules',
'D:\\ProgramDemos\\Web\\node_modules',
'D:\\ProgramDemos\\node_modules',
'D:\\node_modules' ] }
*******provider-exports***********
{ name: { firstName: 'xh', lastName: 'k' } }
*******customer-result***********
{ name: { firstName: 'xh', lastName: 'k' } }
複製代碼
從結果看,爲exports設置任意類型的屬性,module.exports保持同步,能被require返回出去。
第三種情況:
provider.js,爲exports設置任意類型的屬性,並且爲module.exports設置同名的或不同名的任意類型的屬性。
複製代碼
exports.name = {firstName:'xh', lastName:'k'};
//exports.name = "kxh";
/*exports.printName = function(){
console.log("kxh");
};*/
//module.exports.name = {firstName:'wf', lastName:'z'};
module.exports.mail = "[email protected]";
console.log('*******provider-module***********');
console.log(module);
console.log('*******provider-exports***********');
console.log(exports);
複製代碼
customer.js不變。
執行customer.js結果:
複製代碼
*******provider-module***********
{ id: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\provider.js',
exports:
{ name: { firstName: 'xh', lastName: 'k' },
mail: '[email protected]' },
parent:
{ id: '.',
exports: {},
parent: null,
filename: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\customer.js',
loaded: false,
children: [ [Circular] ],
paths:
[ 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\node_modules',
'D:\\ProgramDemos\\Web\\nodejs\\node_modules',
'D:\\ProgramDemos\\Web\\node_modules',
'D:\\ProgramDemos\\node_modules',
'D:\\node_modules' ] },
filename: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\provider.js',
loaded: false,
children: [],
paths:
[ 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\node_modules',
'D:\\ProgramDemos\\Web\\nodejs\\node_modules',
'D:\\ProgramDemos\\Web\\node_modules',
'D:\\ProgramDemos\\node_modules',
'D:\\node_modules' ] }
*******provider-exports***********
{ name: { firstName: 'xh', lastName: 'k' },
mail: '[email protected]' }
*******customer-result***********
{ name: { firstName: 'xh', lastName: 'k' },
mail: '[email protected]' }
複製代碼
從結果看,如果設置不同名的屬性,則爲合併到module.exports並返回,如果是同名屬性則require返回的全是module.exports。
第四種情況:
provider.js,不論爲exports設置社麼樣類型的屬性,直接爲module.exports設置了任意類型對象。
複製代碼
exports.name = {firstName:'xh', lastName:'k'};
//exports.name = "kxh";
/*exports.printName = function(){
console.log("kxh");
};*/
//module.exports = {name:'kxh'};
module.exports = function(){
console.log('kxh');
};
console.log('*******provider-module***********');
console.log(module);
console.log('*******provider-exports***********');
console.log(exports);
複製代碼
customer.js不變。
執行customer.js結果:
複製代碼
*******provider-module***********
{ id: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\provider.js',
exports: [Function],
parent:
{ id: '.',
exports: {},
parent: null,
filename: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\customer.js',
loaded: false,
children: [ [Circular] ],
paths:
[ 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\node_modules',
'D:\\ProgramDemos\\Web\\nodejs\\node_modules',
'D:\\ProgramDemos\\Web\\node_modules',
'D:\\ProgramDemos\\node_modules',
'D:\\node_modules' ] },
filename: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\provider.js',
loaded: false,
children: [],
paths:
[ 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\node_modules',
'D:\\ProgramDemos\\Web\\nodejs\\node_modules',
'D:\\ProgramDemos\\Web\\node_modules',
'D:\\ProgramDemos\\node_modules',
'D:\\node_modules' ] }
*******provider-exports***********
{ name: { firstName: 'xh', lastName: 'k' } }
*******customer-result***********
[Function]
複製代碼
從結果看,不論爲exports設置社麼樣類型的屬性,直接爲module.exports設置了任意類型對象,則require一律返回module.exports。
從上面的四種實踐結果來看:
require返回的是module.exports,在module.exports上可以設置函數、對象實例、基本類型的變量等,因此,一般就是module.exports作爲模塊的到處就行了。
如果想用exports作爲模塊的返回,那麼就爲它設置一個屬性,並且不要在module.exports上設置同名的屬性。