exports与module.exports的区别
牢记一条原则:无论使用 exports暴露成员,或是 module.exports 暴露成员,最终暴露的结果,都是以 module.exports 所指向的对象为准。
1.module 对象
看一下 module对象长什么样子
2.module.exports 和 exports 的联系
在 module 对象中,包含 exports 属性,而我们就是通过这个属性(module.exports),向外暴露(共享)成员的。
exports 是 node 为了简化向外共享成员的代码,提供的一个新方式,在默认情况下,exports 和 module.exports 指向的是同一个对象(为了不混淆,可以理解为 exports 是 module.exports 对象地址的一个引用,exports 本质是一个变量)。
3.module.exports 和 exports 的区别
两者没有区别,是全等的
4.module.exports 和 exports 的使用注意点
一、不恰当的使用方法:exports = xxx;
4.1 论述:
在使用 module.exports 时,我们可以将某一个对象赋值给 module.exports(module.exports = Object),也可以为 module.exports 挂载新属性( module.exports.name = ‘zs’),这些都没有问题,你都可以在引用的文件中拿到修改后的模块成员(module.exports 所指的对象)。
但是,如果你将某一对象或某一变量直接赋值给了 exports(例如:const project = ‘张三’; exports = project; ),那么你在引用的文件中只能拿到一个 {}。
原因是因为 exports 在默认情况下是指向 module.exports 对象的引用,如果为 exports 赋值了,那么也就是说 exports 不再指向 module.exports 所指的对象的地址,而我们向外共享成员的最终结果是 module.exports 所指的对象,如此便会导致错误。
4.2 代码展示:
尝试使用 exports 直接向外共享对象(共享其他数据类型结果一致)
定义两个文件,做一下代码展示与说明
- exports.js 文件
// 定义一个对象
const porject = {
name: 'zs',
age: 20
};
// 尝试使用 exports 对象共享 project 对象
exports = porject;
- index.js 文件
// 导入 exports 模块,试图拿到 exports 中的 project 对象
const ex = require('./exports');
// 打印 exports.js 中向外暴露的对象
console.log(ex);
4.3 重要结论:
module.exports 和 exports 同指一个对象,但是最终暴露结果以 module.exports 的为准,上面的代码中,exports 改变了指向,而我们又没有为 module.exports 挂载任何的属性或方法,所以就拿到了空对象。
画图举例
刚开始 module.exports 和 exports 指向同一个对象
然后 exports 指向了一个新对象
但我们向外暴露时,是以 module.exports 为标准的,也就是向外暴露的是上图中的“原对象”,而不是“新对象”,在上述代码中,我们没有对原对象做任何操作,原对象是没有值的,所以我们导入了 exports.js 之后,得到的是一个空对象。
二、正确的使用方法:exports.xxx = xxx;
4.4 论述:
1.我们可以为 exports 挂载新的属性或方法(exports.name = ‘张三’),向外共享成员也能够拿到想要的修改后的对象
4.5 代码展示:
尝试使用 exports 挂载成员后,向外共享成员。
定义两个文件,做一下代码展示与说明
- exports.js 文件
// 尝试使用 exports 对象挂载 str 属性后,向外共享
exports.str = '张三';
- index.js 文件
// 导入 exports 模块
const ex = require('./exports');
// 打印 exports.js 中向外暴露的成员
console.log(ex);
- 打印结果
4.6 重要结论:
使用 exports 挂载成员的方式不会令 exports 不再指向 module.exports 所指的对象。上述代码中的 exports.str = ‘张三’; 相当于 module.exports.str = ‘张三’;
画图举例
刚开始 module.exports 和 exports 指向同一个对象
然后我们为 exports 挂载了一个 str 的属性
可以清楚得知道,exports.str = ‘张三’; 的操作,只是为 exports 所指对象,添加一个新属性,这并不会使 exports 指向一个新的地址(对象);所以我们可以成功的拿到 { str:‘张三’ };
5. 总结
这种 exports.xxx = xxx; 的使用方法才是恰当的,才能够保证 exports === module.exports。