初学nodejs,该博客当做一篇笔记防止日后遗忘,如有描述不对的地方,望各位指出。
在node的模块系统中,会有多个模块之间互相引用的情况。举个例子,如果A模块如果引用了B模块,而A模块又想拿到B模块中的一些变量与方法,那么就要在B模块中将A模块所需的参数与变量用exports来暴露出去,这就是exports的作用,具体详细内容在这里不详细介绍,总之知道他有这么个作用就行了。
而我们要想将一些东西暴露出去,常见的方法除了有exports,还有一个就是module.exports。这就会有很多小白疑惑,到底这两兄弟应该怎么用以及如何使用。我们先来说说这两的用法。
1、对于exports,我们可以使用以下方法,从以下代码我们可以看出,使用exports的格式为:exports.xxx = xxx。
exports.x = 123 //将x=123暴露出去
exports.a = function(){ //将输出123的a方法暴露出去
console.log("123")
}
2、对于module.exports,我们可以有两种方法进行使用,一种与exports类似,都是在使用module.exports.xxx = xxx的形式,而另一种则是module.exports.xxx = { },在对外暴露的对象对象obj中放入自己想要暴露出去的参数或者方法 ,例如以下代码段:
module.exports.a = 123 //第一种用法
module.exports.b = { //第二种用法
name:"张三",
age:18,
sayHello:function(){
console.log("Hello")
}
}
讲完了module.exports与exports用法,接下来我们讲讲这两姐妹的区别。首先我们会发现,module.exports比exports多了一种导出的方式,很多人可能会对此有疑问。下面就解释一下这个东西。首先,module.exports与exports在本质上是一个东西,为了验证这个观点,我们可以将module.exports == exports打印出来,发现是true,证明了这两确实是一样的。那么他们这两个变量module.exports与exports,指向的就是同一个内存空间,他们变量保存的值是相同的内存空间的地址。看下图可能更好李姐:
学习过前端深浅拷贝的都知道,这两指向同一个对象。而对于引用数据类型,当其中一个通过.xxx的方式将对象当中的某个属性改变时,下次再对该属性进行读取得到的就是改变之后的值。module.exports与exports通过.xxx的方式来向外暴露参数的同时,他们这两个变量本身指向的那个对象并没有改变,而是修改了其中的值而已,所以说module.exports与exports都能通过.xxx的方式暴露参数的原因。可以用一下代码进行简单验证,得到的结果是在控制台输出123和456:
A.js
var a = require("./B").a
var b = require("./B").b
console.log(a);
console.log(b);
B.js
exports.a = 123;
module.exports.b = 456;
接下来讲讲为什么可以直接一个对象赋值给module.exports达到暴露参数的目的而exports却不能。在前边我们也提到过,exports和module.exports这两个其实是变量,保存的是指向一个对象的内存地址,那么如果module.exports={ },这时候修改的就是一个对象中的exports属性,并没有修改变量当中的值,对于最终的效果没什么影响,而exports=module.exports,如果这时候使用exports={ },那么就相当于exports指向断开了,此时我们修改的就是exports这个变量当中的值也就是指向的内存地址而不是对象当中的值,所以在其他模块中就无法得到暴露出去的参数。
我们可以用如下代码来对exports={ }的导出方法进行一个测试。
A.js
var a = require("./B");
console.log(a.name);
a.sayname();
B.js
exports =
{
name:"张三",
sayname:function(){
console.log("123")
}
}
运行A.js后,我们就会发现如下的报错,说明exports={ }这种使用方式行不通
如果换成module.exports,那么此时我们只是修改了对象当中的属性,对于module.exports这个变量的值并没有改变,如下代码进行验证:
A.js
var a = require("./B")
console.log(a.name);
a.sayname();
B.js
module.exports =
{
name:"张三",
sayname:function(){
console.log("123")
}
}
最后得到的结果如下:
总结:
exports不能使用直接给它赋值一个对象的方法来进行参数的暴露,因为这样已经修改了变量的值,指向的地址就不对了,所以exports只能用exports.xxx=xxx的方式。而当我们需要暴露出去的参数以及方法较多时,我们可以使用module.exports={ },在对象中放入需要的参数以及方法,这样就会比较简便,而不至于要写很多module.exports.xxx=xxx或者exports.xxx=xxx。