exports与module.exports的区别

exports与module.exports的区别


释义

1.module.exports 初始值为一个空对象 {}

2.exports 是指向的 module.exports 的引用

3.require() 返回的是 module.exports 而不是 exports

用一句话来说明就是,require能看到的只有require.exports这个对象,他是看不到exports对象的,而我们在编写模块时用到的exports对象实际上只是对module.exports的引用

概念

基本类型:包括Undefined, Null, Boolean, Number和String五种基本数据类型
引用类型:保存在内存中的对象,不能直接操作,只能通过保存在变量中的地址引用对其进行操作

我们要讨论的exports和module.exports是Object类型,属于引用类型

看下面的例子来说明一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var module = {
exports: {
name: "我是module的exports属性"
}
};
var exports = module.exports; //exports是对module.exports的引用,也就是exports现在指向的内存地址和module.exports指向的内存地址是一样的
console.log( module.exports ); /*{name: "我是module的exports属性"}*/
console.log( exports ); /*{name: "我是module的exports属性"}*/
exports.name = "我想改一下名字";
/*
* 因为是引用类型,所以导致两个的值都发生了改变
*/
console.log( module.exports ); //{name: "我想改一下名字"}
console.log( exports ); //{name: "我想改一下名字"}
/*
* 重新定义一个想要导出的模块
*/
var Circle = {
name: "我是一个圆",
func: function(x){
return x*x*Math.PI;
}
};
exports = Circle; /* 此时Circle这个Object在内存中指向了新的地址,所以exports也指向了这个地址,那么exports与原来的地址就断开了联系 */
console.log(module.exports); /* {name: "我想改一个名字"} */
console.log(exports); /* {name: "我是一个圆", func: [Function] */

到这里应该可以看懂了一些,再回到Node.js中,module.exports初始的时候为{},exports也指向这个空对象

那么,如果这样:

1
2
3
4
5
6
7
8
9
exports.name = function(x){
console.log(x);
};
module.exports.name = fucntion(X){
console.log(x);
};
/* 以上两种写法是一样的效果,因为修改的是同一内存地址里的东西 */

再来看另一个例子:

1
2
3
exports = function(x){
console.log(x);
};

上面的function是一个新的内存地址,导致exports与module.exports失去联系,而require的是module.exports这个对象,所以这个模块时导不出去的

还是另一个例子:

1
2
3
module.exports = function(x){
console.log(x);
};

这个是可以正常导出的

# module.exports除了可以导出对象、函数,还可以导出所有的类型,比如字符串,数值。