javascript - Object.assign(module.exports, {...}) 与 module.exports = {...}
问题描述
有人可以举例说明 module.exports = {...} 将如何导致意外行为。
我正在阅读您还不知道 js,我在 https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closures/ch8.md#node遇到了这个-commonjs-modules
一些开发者有替换默认导出对象的习惯,像这样:
// defining a new object for the API module.exports = { // ..exports.. };
这种方法有一些怪癖,包括如果多个这样的模块循环地相互依赖时的意外行为。因此,我建议不要更换该对象。如果您想一次分配多个导出,使用对象文字样式定义,您可以这样做:
Object.assign(module.exports,{ // .. exports .. });
这里发生的事情是使用指定的模块的公共 API 定义 { .. } 对象文字,然后 Object.assign(..) 将所有这些属性的浅拷贝复制到现有的 module.exports 对象上,而不是替换它是方便和更安全的模块行为的一个很好的平衡。
解决方案
该exports
对象是在您的模块运行之前为您的模块创建的,如果存在循环依赖关系,则其他模块可能会在您的模块填充它之前访问该默认对象。如果您替换它,它们可能具有旧的原始对象,而不是(最终)看到你的出口。如果您添加到它,那么即使该对象最初没有您的导出,最终它也会拥有它,即使其他模块在这些导出存在之前访问该对象也是如此。
CJS 模块文档的Cycles 部分中的更多内容。
我们可以修改该部分中的循环示例来演示它:
a.js
(注意变化):
console.log('a starting');
// Removed: `exports.done = false;`
const b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports = {done: true}; // ** Modified this line
console.log('a done');
b.js
(不变):
console.log('b starting');
exports.done = false;
const a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done');
main.js
(不变):
console.log('main starting');
const a = require('./a.js');
const b = require('./b.js');
console.log('in main, a.done = %j, b.done = %j', a.done, b.done);
当你运行它时:
主启动 一个开始 b 开始 在 b 中,a.done = 未定义 b 完成 在 a, b.done = true 完成 在 main 中,a.done = 未定义,b.done = true (节点:2025)警告:在循环依赖中访问模块导出的不存在属性“完成” (使用 `node --trace-warnings ...` 显示警告的创建位置)
旁注:循环使用 JavaScript 自己的模块系统 (ESM) 以不同方式处理,并且由于没有exports
等效对象(您可以访问;从概念上讲),因此不会出现此问题。我建议尽可能使用 ESM。自 v12 以来,Node.js 一直以相当稳定(尽管仍在不断发展)的方式支持它。
推荐阅读
- reactjs - 有没有办法在 ReactJS 中向动态表中添加行?
- installation - 在 MAC 上安装 CPLEX Studio 20 时出现问题
- arrays - 从文本文件中的一些字符串创建数组 - Ruby
- xforms - XFDL 日期约束
- sql-server - 创建触发器以将数据从一个表获取到另一个表并生成时间戳
- nginx - nginx 插件不工作;您现有的配置可能有问题
- c# - 读取和写入多个名为管道c#的消息的问题
- type-conversion - 使用 IrfanView 将地理参考的 .png 文件转换为 .ecw
- jquery - Datatables Gyrocode 复选框扩展,根据条件设置每行的检查状态
- terraform - 是否可以在不重建的情况下从索引中删除 terraform 资源