nodejs中exports與module.exports的用法實踐

只要是在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上設置同名的屬性。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章