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
296 views
in Technique[技术] by (71.8m points)

javascript - ES6 modules: imported constants are undefined at first; they become available later

I use ES6 modules in my JavaScript application. The sources are compiled with webpack and babel. This is a shortened version of the file that causes me trouble:

export const JUST_FORM = 0;
export const AS_PAGE = 1;

console.log(AS_PAGE); // **

export default function doSomething(mode = AS_PAGE) {
  console.log(mode);
  console.log(JUST_FORM);
}

I use this functionality just as you would expect.

import doSomething, { AS_PAGE } from './doSomething'

console.log(AS_PAGE);

doSomething();

When I run the app, it prints three times undefined and only once the expected value AS_PAGE which is the console.log marked with **. However, this is printed last! It shows that:

  • The AS_PAGE constant, when used as default parameter for the doSomething function`, is not defined at the moment of defining the function.
  • The JUST_FORM constant is not defined when doSomething is called.
  • The AS_PAGE constant is not defined when explicitly imported.

Apparently, what's happening here is that only the default export gets parsed and evaluated and the rest of the file is ignored until later. I import this file on several different places in my app (which is quite large at this moment) and at some point those values become actually available. Judging from the console output, it's matter of time, but it is possible that it has a different reason. Obviously, I do the importing exactly the same way in all places.

Anyway, I've written my whole application with the assumption that once I import something, it is immediately available and I can use it in my code. I read (briefly) about how ES6 modules should work and I haven't found anything that would prove this assumption wrong. And it has been working until now.

Also note, that the behavior is the same when I run it with webpack-dev-server or compile it to a single bundle.

Is this behavior really correct? What might be responsible for it?

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

As suggested in the comments, the answer here are circular dependencies.

There is actually no circular dependency present in the code provided in the question (because it's just a simplified snippet of code) but the symptoms are very clear.

The simplest example of a circular dependency is when file A imports file B and file B imports A. Unfortunately, what makes this issue hard to detect sometimes is that the circle can be arbitrarily large, spanning over a huge amount of files.

Circular dependencies are supported in ES6 and they can be used when one is careful enough. However, my takeaway here is that circular dependencies are very often a sign of bad design decisions. Which was exactly my case.


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

...