node种exports和module.exports是什么的区别

node种exports和module.exports的区别_百度知道
node种exports和module.exports的区别
提问者采纳
exports只不过是它的一个辅助工具。当然。所有的exports收集到的属性和方法.exports是node.exports已经具备一些属性和方法。如果.exports而不是exports,module,都赋值给了module,就是module.exports本身不具备任何属性和方法.exports,这有个前提。 最终返回给调用的是module.js真正的接口module
其他类似问题
为您推荐:
一只鞋的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁只要是在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: {},
{ id: '.',
exports: {},
parent: null,
filename: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\customer.js',
loaded: false,
children: [ [Circular] ],
[ '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: [],
[ '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' } },
{ id: '.',
exports: {},
parent: null,
filename: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\customer.js',
loaded: false,
children: [ [Circular] ],
[ '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: [],
[ '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 = "";
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',
{ name: { firstName: 'xh', lastName: 'k' },
mail: '' },
{ id: '.',
exports: {},
parent: null,
filename: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\customer.js',
loaded: false,
children: [ [Circular] ],
[ '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: [],
[ '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: '' }
*******customer-result***********
{ name: { firstName: 'xh', lastName: 'k' },
mail: '' }
从结果看,如果设置不同名的属性,则为合并到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],
{ id: '.',
exports: {},
parent: null,
filename: 'D:\\ProgramDemos\\Web\\nodejs\\TestNode\\customer.js',
loaded: false,
children: [ [Circular] ],
[ '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: [],
[ '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上设置同名的属性。
阅读(...) 评论()node.js中的javascript世界 (二) : module与module.exports - 简书
下载简书移动应用
写了87019字,被133人关注,获得了324个喜欢
node.js中的javascript世界 (二) : module与module.exports
本文件模块(附加模块信息), 可以看作是命名空间的局域写法.
这其实是个功能对象,
在新版本里用来简写module.exports.(通过实现一些简单的不算是语法糖的语法糖)
{ id: '.',
exports: 1,
parent: null,
filename: '/home/king/Work/test.js',
loaded: false,
children: [],
[ '/home/king/Work/node_modules',
'/home/king/node_modules',
'/home/node_modules',
'/node_modules'
可以看到module.exports是其属性.
在模块文件中,发生的事情
var module = {};
var exports = {};
module.exports =
module.id = '';
exports被设定与module.exports指向同一个对象.
与prototype同理, 一旦重写exports或者module.exports,他们的关系都会破坏:
exports = function(){};
千万不要这样写, exports对象被重写
exports.init = function(){};
// 这是向exports指向的对象添加属性,自然也会在module.exports关联
当require('模块')的时候, 返回val = module.exports = exports // exports和module.exports没有被重写的时候
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
被以下专题收入,发现更多相似内容:
简书程序员大本营
投稿须知:
1.本专题仅收录与程序有关的文章。
2.请在代码框里写代码,尽量保证可看性。
· 57120人关注
学学nodejs,学学编程。
· 174人关注
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
选择支付方式:Node.js中的模块接口module.exports浅析
在写node.js代码时,我们经常需要自己写模块(module)。同时还需要在模块最后写好模块接口,声明这个模块对外暴露什么内容。实际上,node.js的模块接口有多种不同写法。这里作者对此做了个简单的总结。
返回一个JSON Object
如下代码是一个简单的示例。
1 var exp = {&
2 & &version&: &1.0.0&,&
3 & &function1&: null,&
4 & &module1&: null,
6 module.exports =
这种方式可以用于返回一些全局共享的常量或者变量,例如
1 // MATH.js
2 var MATH = {
3 & &pi&: 3.14,
4 & &e&: 2.72,
7 module.exports = MATH;
调用方式为
1 var MATH = require(&./MATH&)
2 console.log(MATH.pi);
这种方式还可以用于返回几个require的其他模块,可以实现一次require多个模块
1 // module_collection.js
2 var module_collection = {
3 & &module1&: require(&./module1&),
4 & &module2&: require(&./module2&),
7 module.exports = module_
调用方式为
1 var module_collection = require(&./module_collection&);
2 var module1 = module_collection.module1;
3 var module2 = module_collection.module2;
4 // Do something with module1 and module2
其实这种方式还有个变种,如下,通常可以返回几个函数
&1 // functions.js
&2 var func1 = function() {
&3 & console.log(&func1&);
&6 var func2 = function() {
&7 & console.log(&func2&);
10 exports.function1 = func1;
11 exports.function2 = func2;
调用方式为
1 var functions = require(&./functions&);
2 functions.function1();
3 functions.function2();
返回一个构造函数,也就是一个类
如下是一个简单的示例。
&1 // CLASS.js
&2 var CLASS = function(args) {
&3 & this.args =
&6 CLASS.prototype.func = function() {
&7 & console.log(&CLASS.func&);
&8 & console.log(this.args);
11 module.exports = CLASS;
调用方法为
1 var CLASS = require(&./CLASS&)
2 var c = new CLASS(&arguments&);
返回一个普通函数
如下是一个简单的示例
1 // func.js
2 var func = function() {
3 & console.log(&this is a testing function&);
6 module.exports =
调用方法为
1 var func = require(&./func&);
返回一个对象object
如下是一个简单的示例
&1 // CLASS.js
&2 var CLASS = function() {
&3 & this.say_hello = &hello&;
&6 CLASS.prototype.func = function() {
&7 & console.log(&I say & + this.say_hello);
10 module.exports = new CLASS();
调用方法为
1 var obj = require(&./CLASS&);
2 obj.func();
有时候我们需要模块返回一个单例 singleton. 可以利用上面的方式1和方式4来实现。也就是如下两种形式
1 // MATH.js
2 var MATH = {
3 & &pi&: 3.14,
4 & &e&: 2.72,
7 module.exports = MATH;
&1 // CLASS.js
&2 var CLASS = function() {
&3 & this.say_hello = &hello&;
&6 CLASS.prototype.func = function() {
&7 & console.log(&I say & + this.say_hello);
10 module.exports = new CLASS();
最后,真的很喜欢Script这个语言,很方便。而且node.js的出现极大的增强了这门语言的能力。看好它!跟我学Nodejs(三)--- Node.js模块
简介及资料
&&& 通过Node.js的官方API可以看到Node.js本身提供了很多核心模块 http://nodejs.org/api/ ,这些核心模块被编译成二进制文件,可以require('模块名')去获取;核心模块具有最高的加载优先级(有模块与核心模块同名时会体现)
&&& (本次主要说自定义模块)
&&& Node.js还有一类模块为文件模块,可以是JavaScript代码文件(.js作为文件后缀)、也可以是JSON格式文本文件(.json作为文件后缀)、还可以是编辑过的C/C++文件(.node作为文件后缀);
&&& 文件模块访问方式通过require('/文件名.后缀')&&& require('./文件名.后缀')&&& requrie('../文件名.后缀') 去访问,文件后缀可以省略;以"/"开头是以绝对路径去加载,以"./"开头和以"../"开头表示以相对路径加载,而以"./"开头表示同级目录下文件,
&&& 前面提到文件后缀可以省略,Nodejs尝试加载的优先级 js文件 & json文件 & node文件
创建一个自定义模块
&  以一个计数器为例
代码如下:var outputVal& = 0;&&&& //输出值var increment = 1;&&& //增量/* 设置输出值 */function seOutputVal (val) {&&& outputVal =}/* 设置增量 */function setIncrement(incrementVal){&&& increment = incrementV}/* 输出 */function printNextCount(){&&& &&& outputVal +=&&& console.log(outputVal) ;}function printOutputVal() {&&& console.log(outputVal);}exports.seOutputVal = seOutputVexports.setIncrement = setImodule.exports.printNextCount = printNextC自定义模块 示例源码
示例中重点在于exports和module.提供了外部访问的接口,下面调用一下看看效果吧
调用自定义模块
代码如下:/*&&& 一个Node.js文件就是一个模块,这个文件可能是Javascript代码、JSON或者编译过的C/C++扩展。&&& 重要的两个对象:&&& require是从外部获取模块&&& exports是把模块接口公开&&& */var counter = require('./1_modules_custom_counter');console.log('第一次调用模块[1_modules_custom_counter]');counter.seOutputVal(10);&&&&&&&&&&&&&& //设置从10开始计数counter.setIncrement (10);&&&&&&&&&&&& //设置增量为10counter.printNextCount();counter.printNextCount();counter.printNextCount();counter.printNextCount();/*&&& require多次调用同一模块不会重复加载*/var counter = require('./1_modules_custom_counter');console.log('第二次调用模块[1_modules_custom_counter]');counter.printNextCount();自定义模式调用 源码
&&& 运行可以发现通过exports和module.exports对外公开的方法都可以访问!
&&& 示例中可以看到,我两次通过require('./1_modules_custom_counter')获取模块,但是第二次引用后调用printNextCount()方法确从60开始~~~
&&& 原因是node.js通过requirerequire多次调用同一模块不会重复加载,Node.js会根据文件名缓存所有加载过的文件模块,所以不会重新加载了
&&& 注意:通过文件名缓存是指实际文件名,并不会因为传入的路径形式不一样而认会是不同的文件&&&&
&&& 在我创建的1_modules_custom_counter文件中有一个printOutputVal()方法,它并没有通过exports或module.exports提供对外公开访问方法,
&&& 如果1_modules_load文件中直接访问运行会出现什么样的情况呢?
&&& 答案是:TypeError: Object #&Object& has no method 'printOutputVal'
exports和module.exports 区别
经过上面的例子,通过exports和module.exports对外公开的方法都可以访问!那既然两种都能达到效果,但总得有点区别的吧~~~用个例子看看吧!
代码如下:var counter& = 0;&&&& exports.printNextCount = function (){&&& &&& counter += 2;&&& console.log(counter);}var isEq = (exports === module.exports);console.log(isEq);2_modules_diff_exports.js 文件源码
下面再新建个2_modules_diff_exports_load.js文件调用一下
代码如下:var Counter = require('./2_modules_diff_exports');Counter.printNextCount();
&&& 调用后,执行结果如上图
&&& 我在2_modules_diff_exports_load.js文件中输出了isEq的值& ( var isEq = (exports === module.exports); ),返回的true
&&& PS:注意是三个等号,如果不清楚自已查查资料吧!
不用急着下结论,把这两个JS文件分别改成module.exports对应的代码
代码如下://修改后的2_modules_diff_exports.js源码如下var counter& = 0;&&&& module.exports = function(){&&& &&& counter += 10;&&& this.printNextCount = function()&&& {&&&&&&& console.log(counter);&&& &&& }}var isEq = (exports === module.exports);console.log(isEq);
代码如下://修改后的2_modules_diff_exports_load.js文件源码如下var Counter = require('./2_modules_diff_exports');var counterObj = new Counter();counterObj.printNextCount();
&&& 调用后,执行结果如上图
&&& 我在2_modules_diff_exports_load.js文件中输出了isEq的值& ( var isEq = (exports === module.exports); ),返回的false,这与用先前得到的结果不一致!
&&& PS:不要用Counter.printNextCount();去访问,你只会得到一个错误的提示
&&& API提供了解释
&&& http://nodejs.org/api/modules.html
&&& Note that exports is a reference to module.exports making it suitable for augmentation only. If you are exporting a single item such as a constructor you will want to use module.exports directly instead&&& exports仅仅是module.exports的一个地址引用。nodejs只会导出module.exports的指向,如果exports指向变了,那就仅仅是exports不在指向module.exports,于是不会再被导出
&&& 参考其它理解:
&&& /node-js-exports-vs-module-exports.html
&&& http://zihua.li/2012/03/use-module-exports-or-exports-in-node/
&&& module.exports才是真正的接口,exports只不过是它的一个辅助工具。 最终返回给调用的是module.exports而不是exports。&&& 所有的exports收集到的属性和方法,都赋值给了Module.exports。当然,这有个前提,就是module.exports本身不具备任何属性和方法。&&& 如果,module.exports已经具备一些属性和方法,那么exports收集来的信息将被忽略。
exports和module.exports 覆盖
上面也也基本明白了exports和module.exports的关系和区别,但如果同时针对printNextCount()方法存在exports和module.exports,结果如何?
&&& 从结果可以看出,并没有报错,表示可以这么定义,但最终module.exports覆盖了exports
&&& 虽然结果不会报错,如果这么用开发中难免会有一些问题存在,所以
&&& 1.最好别分别定义module.exports和exports
&&& 2.NodeJs开发者建议导出对象用module.exports,导出多个方法和变量用exports
&  API中还提供了其它的方法,就不细讲了,在上面例子的基础上自已动手一输出就知道了
  module.id
  返回string类型的模块标识,一般为完全解析后的文件名
  module.filename
  返回一个string类型的完全解析后文件名
  module.loaded
  返回一个bool类型,表示是否加载完成
  module.parent
  返回引用该模块的模块
  module.children
  返回该模块引用的所有模块对象的数组
顶一下(0) 踩一下(0)
热门标签:}

我要回帖

更多关于 module.exports 写法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信