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

时间:2016-05-29 23:10:25

标签: javascript ecmascript-6 babel

我在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);
}

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

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

console.log(AS_PAGE);

doSomething();

当我运行该应用时,它会打印三次undefined并且仅打印一次AS_PAGE console.log,标记为**。但是,这是最后打印的!它表明:

  • AS_PAGE常量(用作doSomething函数的默认参数)在定义函数时未定义。
  • 调用JUST_FORM时未定义doSomething常量。
  • 显式导入时未定义AS_PAGE常量。

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

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

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

这种行为是否真的正确?可能对此负责的是什么?

1 个答案:

答案 0 :(得分:28)

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

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

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

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