简体   繁体   English

Node.js 导出的行为与 ES6 模块不同

[英]Node.js export behaves differently from ES6 modules

In ES6 modules, this works as expected:在 ES6 模块中,这按预期工作:

  • index.js index.js
import { foo, init } from "./foo";

init();
console.log(foo);  // 42
  • foo.js foo.js
export let foo;
export const init = () => {
  foo = 42;
};

However in Node.js, when I tried the same thing, the foo didn't get updated.然而在 Node.js 中,当我尝试同样的事情时, foo没有得到更新。

How can I make the foo updates to 42 after init() is run?运行init()后如何将foo更新为42

  • index.js index.js
let { foo, init } = require('./foo');

init();
console.log(foo);  // undefined
  • foo.js foo.js
let foo;

const init = () => {
    foo = 42;
};

module.exports = {
    init,
    foo
};

I know I could export a function getFoo() and returns the updated foo , but it seems not very convenient.我知道我可以导出 function getFoo()并返回更新后的foo ,但似乎不太方便。

What's the proper way to export a variable in Node.js that may change after?导出 Node.js 中可能会发生变化的变量的正确方法是什么?

The behavior here, which you can see in ES6 modules:这里的行为,你可以在 ES6 模块中看到:

console.log(foo);  // undefined
init();
console.log(foo);  // 42

should feel pretty odd in comparison to how JS normally works - foo appears to be a local identifier, but if it happens to be an import from another module, if the other module's export changes, the foo binding wherever it's imported will change as well.与 JS 通常的工作方式相比,应该感觉很奇怪 - foo似乎是一个本地标识符,但如果它恰好是从另一个模块导入的,如果另一个模块的导出发生更改,则无论它被导入的foo绑定也会发生变化。

Without using ES6 modules, there is no (reasonable) way to replicate that sort of behavior using a single identifier.如果不使用 ES6 模块,就没有(合理的)方法可以使用单个标识符来复制这种行为。

You can use ES6 modules in Node if you want, though.不过,如果你愿意,你可以在 Node 中使用 ES6 模块。 Use the original code with the ES6 module syntax, and then run:使用带有 ES6 模块语法的原始代码,然后运行:

node --experimental-modules index.mjs

Build systems like Webpack can also transpile code written in ES6 modules into vanilla JS, though such transpiled code ends up turning the imports into a namespace object.像 Webpack 这样的构建系统也可以将 ES6 模块中编写的代码转译为 vanilla JS,尽管这样的转译代码最终会将导入转换为命名空间 object。 Eg, this:例如,这个:

import { foo, init } from "./foo";

init();
console.log(foo);  // 42

will turn into something like会变成类似的东西

const fooNamespace = __webpack_require__("./foo.js");
fooNamespace.init();
console.log(fooNamespace.foo);

It's just like if you had a reference to an object which, when a function inside it is called, mutates the object.就像您引用了 object 一样,当调用其中的 function 时,它会改变 object。 You could implement this if you wanted.如果你愿意,你可以实现它。

const obj = {
  foo: undefined,
  init() { obj.foo = 42 }
};
module.exports = obj;

Although one can use ES6 modules to make imported identifiers seemingly reassign themselves on their own, keep in mind that, since such code is potentially confusing, some prefer to avoid such patterns entirely .尽管可以使用 ES6 模块使导入的标识符看起来像是自己重新分配,但请记住,由于此类代码可能会造成混淆,因此有些人更愿意完全避免此类模式

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM