module和exports是Node.js给每个js⽂件内置的两个对象。可以通过console.log(module)和console.log(exports)打印出来。如果你在main.js 中写⼊下⾯两⾏,然后运⾏$ node main.js:
console.log(exports);//输出:{}
console.log(module);//输出:Module {..., exports: {}, ...} (注:...代表省略了其他⼀些属性)
从打印咱们可以看出,module.exports和exports⼀开始都是⼀个空对象{},实际上,这两个对象指向同⼀块内存。这也就是说module.exports和exports是等价的(有个前提:不去改变它们指向的内存地址)。
例如:exports.age = 18和module.export.age = 18,这两种写法是⼀致的(都相当于给最初的空对象{}添加了⼀个属性,通过require得到的就是{age: 18})。
但它们之间确实存在一些关键的区别。
首先,module.exports 实际上是 Node.js 中每个模块的一个对象,它用于导出模块公开的接口。而 exports 实际上是 module.exports 的一个引用,这意味着最初 exports 和 module.exports 指向同一个对象。
然而,由于 exports 只是 module.exports 的一个引用,所以如果你直接修改 exports 的引用(比如让它指向一个新的对象),那么它就不会再和 module.exports 指向同一个对象了。这种情况下,当你尝试从其他文件 require 这个模块时,你将得到 module.exports 指向的对象,而不是 exports 指向的新对象。
因此,通常建议直接使用 module.exports 来导出模块,以避免可能的混淆和错误。
这里有一个简单的例子来说明这种区别:
javascript
// 假设这是 moduleA.js
exports.hello = function() {
console.log('Hello from exports!');
};
// 这样做是安全的,因为我们只是在向 exports 对象添加属性
// 但是如果我们这样做:
exports = {
sayHello: function() {
console.log('Hello from new exports object!');
}
};
// 那么在另一个文件中 require('moduleA') 将不会得到 sayHello 函数,
// 因为我们改变了 exports 的引用,而 require 返回的是 module.exports 的值
所以,为了保持代码的清晰和可维护性,最好直接使用 module.exports 来导出模块。