在我们使用nodejs引入模块时,我们往往在模块文件中可能会纠结module.exports和exports它们究竟是什么区别?为了彻底明白其区别,我们来看一个例子。在模块中,只输入下述三行代码:
// module.js
console.log('module', module)
console.log('module.exports', module.exports)
console.log('exports', exports)
用node运行module.js让我们直接来看输出结果:
这个时候,也许你就会纳闷了,为什么module没定义,直接console.log输出它不报错吗?这个地方有一个关键所在,在我们使用node加载模块时,Node.js在模块编译过程将模块包装成一个闭包,最终返回类似这样的代码:
(function (exports, require, module, __filename, __dirname) {
// module code...
});
其中,module是模块本身,它跟exports的关系是:
exports = module.exports = {};
这下,你可能就彻底明白了,为什么在未定义module和module.exports时,代码中直接console.log时不会报错了。
那么使用module.exports和exports对模块进行输出有什么区别呢?
这个时候,你就要细想一下刚刚我们在分别输出module、module.exports和exports它们之间的区别了。
一句话概括:module.exports和exports区别就类似于,下面例子中a和b的区别
var a = {} // a类似于module.exports
var b = a // b类似于exports
1)exports和module.exports输出的都是一个对象
_module1.js 使用exports导出
exports.sayName = function(_name) {
console.log('say ' + _name)
}
let _name = ''
exports.name = function(name) {
_name = name
console.log(name)
}
_module2.js使用module.exports导出
module.exports = {
name: function (name) {
_name = name
console.log(name)
},
sayName: function (_name) {
console.log('say ' + _name)
},
}
在使用require引入模块时,两者是等价的
结果均为:
2)exports可以不断的添加属性或方法,多个module.exports导出时会覆盖前一个module.exports
多个exports:
exports.sayName = function(_name) {
console.log('say ' + _name)
}
let _name = ''
exports.name = function(name) {
_name = name
console.log(name)
}
输出结果:
多个module.exports:
module.exports = {
name: function (name) {
_name = name
console.log(name)
},
sayName: function (_name) {
console.log('say ' + _name)
},
}
// 多个module.exports时,只会输出最后一个,因为会发生覆盖
module.exports = {
name: function (name) {
_name = name
console.log(name)
},
}
输出结果:
3)当同时使用exports和module.exports输出时,只会输出最后一个module.exports的内容
module.exports = {
name: function (name) {
_name = name
console.log(name)
},
sayName: function (_name) {
console.log('say ' + _name)
},
}
// 只输出当前module
module.exports = {
name: function (name) {
_name = name
console.log(name)
},
}
exports.sayName = function(_name) {
console.log('say ' + _name)
}
输出结果:
通过以上比较,我们可以有个大概的结论,mudule.exports和exports在一定程度上,它们是等价的。但它们也有各自的区别,我们在使用时,在一个模块中只使用其中一者,这样可以最大程度的规避出现错误。