javascript - Object.assign(module.exports, {...}) 与 module.exports = {...}

标签 javascript node.js commonjs

有人可以用示例解释 module.exports = {...} 将如何导致意外行为。

我读到你还不知道 js,我在 https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closures/ch8.md#node-commonjs-modules

Some developers have the habit of replacing the default exports object, like this:

// defining a new object for the API
module.exports = {
    // ..exports..
};

There are some quirks with this approach, including unexpected behavior if multiple such modules circularly depend on each other. As such, I recommend against replacing the object. If you want to assign multiple exports at once, using object literal style definition, you can do this instead:

Object.assign(module.exports,{
   // .. exports ..
});

What's happening here is defining the { .. } object literal with your module's public API specified, and then Object.assign(..) is performing a shallow copy of all those properties onto the existing module.exports object, instead of replacing it This is a nice balance of convenience and safer module behavior.

最佳答案

exports 对象是在模块运行之前为您的模块创建的,并且如果存在循环依赖关系,则其他模块可能会先于您的模块访问该默认对象。填写它。如果您替换它,他们可能拥有旧的原始对象,并且(最终)看不到您的导出。如果您添加到它,那么即使该对象最初没有您的导出,最终它也会拥有它,即使其他模块在这些导出存在之前访问了该对象。

更多内容请参见 Cycles section CJS 模块文档。

我们可以调整该部分中的循环示例来演示它:

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);

当你运行它时:

main starting
a starting
b starting
in b, a.done = undefined
b done
in a, b.done = true
a done
in main, a.done = undefined, b.done = true
(node:2025) Warning: Accessing non-existent property 'done' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)

旁注:循环的处理方式与 JavaScript 自己的模块系统 (ESM) 不同,并且由于没有 exports 等效对象(您可以访问;概念上存在),因此不会出现此问题。我建议尽可能使用 ESM。自 v12 以来,Node.js 就以相当稳定(尽管仍在不断发展)的方式支持它。

关于javascript - Object.assign(module.exports, {...}) 与 module.exports = {...},我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63371870/

相关文章:

javascript - 如何使用 jQuery 对字符串进行子字符串化

javascript - 切换 Bootstrap 4 桌面导航的滑入动画

node.js - 消息: path is required

javascript - JavaScript 中的 Split 函数出现异常

javascript - Javascript 数字中的位数

Javascript - 通过预签名 URL 将 CSV 上传到 S3 - 文件包含边界数据

node.js - 我应该使用快速的客户端 react 路由器还是服务器端 react 路由器?

javascript - 以下链式语句在 JavaScript 中意味着什么?

javascript - 将 CommonJS 3rd 方库包装为 AMD 模块

angularjs - 如何使 Typescript 与 SystemJS 和 Angular 一起使用成为可能?