Node.js 中 exports 与 module.exports 的区别详解

作者:后端茶话

时间:2026-10-26

浏览:320

本文深入解析Node.js中exports与module.exports的关系。明确module.exports才是模块的真实接口,exports仅是其引用。通过代码示例说明当module.exports被重新赋值时,exports属性将被忽略,模块返回新定义的值。掌握这一机制有助于避免模块导出错误,灵活使用对象、函数或数组等任意JavaScript类型作为模块出口。

文章目录

Node.js模块基础与exports用法

在Node.js开发中,你应当对模块系统中的exports对象非常熟悉,它是构建和导出模块接口的常用方式。以rocker.js文件为例进行说明。


示例代码如下:

 
exports.name = function() {
console.log('My name is Lemmy Kilmister');
}; 

在其他文件中,可以通过以下方式引用该模块:


示例代码如下:

 
var rocker = require('./rocker.js');
rocker.name(); // 输出 'My name is Lemmy Kilmister'

那到底Module.exports是什么呢?它是否合法呢?

module.exports与exports的核心关系

实际上,module.exports才是模块真正的接口,而exports仅仅是一个辅助工具。Node.js最终返回给调用者的内容是module.exports,而非exports。



通常情况下,exports收集到的所有属性和方法都会被赋值给module.exports。但这一行为有一个前提条件:module.exports本身必须是一个空对象,即不具备任何预先定义的属性和方法。如果module.exports已经被赋予了特定的值或方法,那么通过exports添加的属性将被忽略。



module.exports覆盖机制与类型示例

修改rocker.js文件内容如下:


示例代码如下:

 
module.exports = 'ROCK IT!';
exports.name = function() {
console.log('My name is Lemmy Kilmister');
}; 

再次引用并执行rocker.js模块:


示例代码如下:

 
var rocker = require('./rocker.js');
rocker.name(); // 报错:TypeError: Object ROCK IT! has no method 'name'

此时出现错误提示:对象“ROCK IT!”没有name方法。


在上述例子中,rocker模块忽略了通过exports收集的name方法,直接返回了字符串“ROCK IT!”。这证明了模块并不一定非要返回一个实例化对象。模块的返回值可以是任何合法的JavaScript数据类型,包括布尔值、数字、日期、JSON对象、字符串、函数或数组等。



模块的具体类型完全取决于你赋予module.exports的值。如果你没有显式地为module.exports设置任何属性或方法,那么模块将返回通过exports附加到module.exports上的属性集合。



以下示例展示如何将模块定义为一个类:


示例代码如下:

 
module.exports = function(name, age) {
this.name = name;
this.age = age;
this.about = function() {
console.log(this.name +' is '+ this.age +' years old');
}; 
}; 

应用该模块的方式如下:


示例代码如下:

 
var Rocker = require('./rocker.js');
var r = new Rocker('Ozzy', 62);
r.about(); // 输出 Ozzy is 62 years old

另一个示例展示如何将模块定义为一个数组:


示例代码如下:

 
module.exports = ['Lemmy Kilmister', 'Ozzy Osbourne', 'Ronnie James Dio', 'Steven Tyler', 'Mick Jagger'];

应用该模块的方式如下:


示例代码如下:

 
var rocker = require('./rocker.js');
console.log('Rockin in heaven: ' + rocker[2]); // 输出 Rockin in heaven: Ronnie James Dio

现在可以明确:如果你希望模块导出特定类型的值(如字符串、数组或构造函数),应使用module.exports;如果你希望导出一个典型的实例化对象,则使用exports更为方便。



两种导出方式的对比与最佳实践

向module.exports添加属性与向exports添加属性在语法上类似。例如:


示例代码如下:

 
module.exports.name = function() {
console.log('My name is Lemmy Kilmister');
}; 

同样,使用exports也可以实现类似效果:


示例代码如下:

 
exports.name = function() {
console.log('My name is Lemmy Kilmister');
}; 

需要注意的是,这两种写法的结果并不完全相同。如前所述,module.exports是真正的接口,exports只是其辅助工具。通常推荐使用exports进行导出,除非你需要将模块从默认的“实例化对象”更改为其他特定类型。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章