nodejs中exports与module.exports的实践
只要是在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
^-^
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述