一、模块导出机制的区别
在Node.js中,module.exports
和exports
都是用于导出模块内容的机制,但两者存在关键差异,主要体现在作用域和最终导出结果上。
1、module.exports
的原始作用
module.exports
是CommonJS模块系统的默认导出对象。当其他文件通过require
导入该模块时,返回的就是module.exports
指向的对象。初始状态下,module.exports
是一个空对象{}
,但可以完全重新赋值。
// 直接替换导出对象
module.exports = { key: 'value' };
2、exports
的辅助角色
exports
是module.exports
的一个引用,初始时两者指向同一内存地址。通过exports
添加属性时,会同步修改module.exports
的内容,因为操作的是同一对象。
// 添加属性(有效)
exports.key = 'value';
// 等同于
module.exports.key = 'value';
二、关键差异点
1、重新赋值的影响
若直接对exports
重新赋值(而非添加属性),会切断与module.exports
的引用关系。此时exports
指向新对象,而module.exports
仍保持原状,导致导出失败。
// 错误用法:切断引用
exports = { key: 'value' }; // 无效导出
2、导出优先级
Node.js最终只认module.exports
。若两者同时存在不同内容,以module.exports
为准。
exports.key1 = 'value1';
module.exports = { key2: 'value2' };
// 最终导出 { key2: 'value2' }
三、使用场景建议
- 导出单一对象或函数
直接使用module.exports
替换整个对象:
module.exports = function() { ... };
- 扩展模块功能
使用exports
添加多个属性或方法:
exports.method1 = () => {...};
exports.method2 = () => {...};
四、常见问题示例
以下代码会导致导出为空对象,因为exports
被重新赋值:
exports = { a: 1 };
// 正确写法应改为
module.exports = { a: 1 };
五、底层机制解析
模块加载时实际执行流程:
这种设计允许灵活操作,但需注意引用关系。