只要是在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

^-^

nodejs中exports与module.exports的实践的更多相关文章

  1. nodejs模块中exports和module.exports的区别

    通过Node.js的官方API可以看到Node.js本身提供了很多核心模块 http://nodejs.org/api/ ,这些核心模块被编译成二进制文件,可以require('模块名')去获取:核心 ...

  2. nodejs中exports与module.exports的区别详细介绍

    如果模块是一个特定的类型就用Module.exports.如果模块是一个典型的"实例化对象"就用exports. exports.name = function() { conso ...

  3. nodejs中的exports和module.exports

    module是随文件而生的全局变量,它有exports属性,这个属性默认是一个空的字典. node的设计者画蛇添足有定义了一个exports全局变量,export指向module.exports所指向 ...

  4. 通过Anuglar Material串串学客户端开发 - NodeJS模块机制之Module.Exports

    module.exports 前文讲到在Angular Material的第二个编译文件docs/gulpfile.js中却看到了一个奇怪的东西module.exports那么module.expor ...

  5. nodeJS实战:自定义模块与引入,不同模块的函数传递及回调处理,exports与module.exports(基于nodejs6.2.0)

    前言:本文基于上一篇文章中的源代码进行改写,地址:http://blog.csdn.net/eguid_1/article/details/52182386 注意:为什么不用module.export ...

  6. Node.js中exports,module.exports以及require方法

    在Node.js中,使用module.exports.f = ...与使用exports.f = ...是一样的,此时exports就是module.exports的一种简写方式.但是,需要注意的是, ...

  7. nodeJS学习(9)--- nodeJS模块:exports vs module.exports

    模块简介: 通过Node.js的官方API可以看到Node.js本身提供了很多核心模块 http://nodejs.org/api/ 这些核心模块被编译成二进制文件,可以 require('模块名') ...

  8. Node.js中exports与module.exports的区别

    原文:http://www.hacksparrow.com/node-js-exports-vs-module-exports.html 你肯定对Node.js模块中用来创建函数的exports对象很 ...

  9. Node.js中的exports与module.exports的区分

    1. module应该是require方法中,上下文中的对象 2. exports对象应该是上下文中引用module.exports的新对象 3. exports.a = xxx 会将修改更新到mod ...

  10. 【nodejs】exports 和 module.exports 的区别

    require 用来加载代码,而 exports 和 module.exports 则用来导出代码.但很多新手可能会迷惑于 exports 和 module.exports 的区别,为了更好的理解 e ...

随机推荐

  1. 设计模式之美:Dynamic Property(动态属性)

    索引 别名 意图 结构 参与者 适用性 效果 实现 实现方式(一):Dynamic Property 的示例实现. 别名 Property Properties Property List 意图 使对 ...

  2. [.net 面向对象编程基础] (20) LINQ使用

    [.net 面向对象编程基础] (20)  LINQ使用 通过上节LINQ的基础知识的学习,我们可以开始使用LINQ来进行内存数据的查询了,我们上节说了LINQ的定义为:Language Integr ...

  3. Comet实现的网页聊天程序

    “上一篇”介绍了我在c/s程序中用了那些技术,如今只谈c/s不谈b/s那未免out了,势必要写一写b/s的程序与大家共勉. 回忆做技术这些年,06年每天盯着“天轰穿”的视频不亦乐乎,估计那是一代程序员 ...

  4. SVM-线性可分支持向量机

    SVM-线性可分支持向量机 如果您想体验更好的阅读:请戳这里littlefish.top 函数间隔和几何间隔 给定线性可分训练数据集,通过间隔最大化或等价地求解相应的凸二次规划问题学习得到的分离超平面 ...

  5. [stm32] STM32的通用定时器TIMx系统了解

    通用定时器(TIMx) 一.TIMx简介 二.TIMx主要功能 三.TIMx功能描述 3.1 时基单元 3.2 计数器模式 3.3 时钟选择 3.4 捕获/比较通道 3.5 输入捕获模式 3.6 PW ...

  6. 用DirectX实现魔方(二)

    这篇说一下如何构造魔方,主要包括魔方几何体的构造及纹理贴图.以下论述皆以三阶魔方为例,三阶魔方共有3 x 3 x 3 = 27个小立方体. 构造魔方 在第一篇里面说过,最初模型用的是微软的.x文件格式 ...

  7. 移动APP的自动化测试

    开发移动应用,最耗时耗力的就是手动测试APP的每个功能点或修复bug.有人就会提议App的业务逻辑可以使用nUnit或xUnit测试单元来辅助完成.那用户界面要如何测试?众所周知,移动设备多种多样,数 ...

  8. 关于session的小结

    session的原理 Session对象的原理在于,服务器可以为客户端创建并维护一个所谓的Session对象,用于存放数据. 在创建Session对象的同时,服务器将会为该Session对象产生一个唯 ...

  9. Atitit  数据存储的分组聚合 groupby的实现attilax总结

    Atitit  数据存储的分组聚合 groupby的实现attilax总结 1. 聚合操作1 1.1. a.标量聚合 流聚合1 1.2. b.哈希聚合2 1.3. 所有的最优计划的选择都是基于现有统计 ...

  10. PHP面向对象 三大特性

    1.封装 目的:就是为了让类更加安全 做法: 1 要将成员做成私有的 2 在类里面做方法来间接访问成员变量 3 在方法里面加控制 简单的: 第一个魔术方法:给变量赋值的        __set fu ...