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 = "kxh@kxh.com";

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: 'kxh@kxh.com' },
  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: 'kxh@kxh.com' }
*******customer-result***********
{ name: { firstName: 'xh', lastName: 'k' },
  mail: 'kxh@kxh.com' }

从结果看,如果设置不同名的属性,则为合并到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上设置同名的属性。

 

end

^-^

 

posted @ 2014-08-25 23:49  白色的海  阅读(12314)  评论(12编辑  收藏  举报