ES6模块:导入的常量最初是未定义的; 他们以后可以使用

tob*_*bik 26 javascript babel ecmascript-6

我在我的JavaScript应用程序中使用ES6模块.源代码是用webpack和babel编译的.这是文件的缩短版本,这会给我带来麻烦:

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);
}
Run Code Online (Sandbox Code Playgroud)

我正如您期望的那样使用此功能.

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

console.log(AS_PAGE);

doSomething();
Run Code Online (Sandbox Code Playgroud)

当我运行的应用程序,它打印三次undefined且仅一次的预期值AS_PAGE也就是console.log标记**.但是,这是最后打印的!它表明:

  • AS_PAGE当用作doSomething函数`的默认参数时,常量在定义函数时未定义.
  • JUST_FORM当常量没有定义doSomething被调用.
  • AS_PAGE明确的导入时没有定义的常量.

显然,这里发生的事情是只有default导出被解析和评估,文件的其余部分将被忽略,直到稍后.我在我的应用程序中的几个不同位置导入此文件(此时此刻非常大),并且在某些时候这些值实际上可用.从控制台输出来看,这是时间问题,但它可能有不同的原因.显然,我在所有地方都以完全相同的方式进口.

无论如何,我已经编写了我的整个应用程序,假设一旦我导入了一些东西,它立即可用,我可以在我的代码中使用它.我(简要地)阅读了ES6模块应该如何工作,我没有找到任何可以证明这个假设错误的东西.它一直在努力.

另请注意,当我运行它webpack-dev-server或将其编译为单个包时,行为是相同的.

这种行为是否真的正确?可能有什么责任呢?

tob*_*bik 36

正如评论中所建议的,这里的答案是循环依赖.

在问题中提供的代码中实际上没有循环依赖(因为它只是一个简化的代码片段),但症状非常清楚.

循环依赖的最简单的例子是文件A导入文件B和文件B导入A.不幸的是,有时候难以检测到这个问题的原因是圆圈可以任意大,跨越大量文件.

ES6支持循环依赖,当一个人足够小心时可以使用它们.然而,我在这里得到的结论是,循环依赖通常是糟糕的设计决策的标志.这正是我的情况.

  • 这绝对是问题所在。没有意识到 `import { someThing } from "SomeIndex"` 实际上会导入 "SomeIndex" 中的所有内容,而不仅仅是一件事。在这种情况下,我从包含我正在处理的组件的索引中导入组件。类似于 `SomeIndex 导出 { Button, ColoredButton}` `ColoredButton 从 SomeIndex` 导入 { Button } 。 (4认同)