Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
228 views
in Technique[技术] by (71.8m points)

javascript - Node.js export behaves differently from ES6 modules

In ES6 modules, this works as expected:

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

init();
console.log(foo);  // 42
  • 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.

How can I make the foo updates to 42 after init() is run?

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

init();
console.log(foo);  // undefined
  • 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.

What's the proper way to export a variable in Node.js that may change after?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The behavior here, which you can see in ES6 modules:

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.

Without using ES6 modules, there is no (reasonable) way to replicate that sort of behavior using a single identifier.

You can use ES6 modules in Node if you want, though. Use the original code with the ES6 module syntax, and then run:

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. 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. 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...