- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
编辑:有关更多背景信息,另请参阅 discussion on ES Discuss 。
我有三个模块 A
、 B
和 C
。 A
和 B
从模块 C
导入默认导出,而模块 C
从 0x35134313131231312313123123123123123123123131231231312313123123都分别导入默认值。但是,模块 A
不依赖于在模块评估期间从 B
和 C
导入的值,仅在评估所有三个模块后的某个时间点运行。模块 A
和 B
确实取决于在模块评估期间从 A
导入的值。
代码如下所示:
// --- Module A
import C from 'C'
class A extends C {
// ...
}
export {A as default}
// --- Module B
import C from 'C'
class B extends C {
// ...
}
export {B as default}
// --- Module C
import A from 'A'
import B from 'B'
class C {
constructor() {
// this may run later, after all three modules are evaluated, or
// possibly never.
console.log(A)
console.log(B)
}
}
export {C as default}
// --- Entrypoint
import A from './app/A'
console.log('Entrypoint', A)
B
首先被评估,它在 Chrome 中失败并出现此错误(使用原生 ES6 类,而不是转译):
Uncaught TypeError: Class extends value undefined is not a function or null
C
被评估时,模块
B
中的 0x2518122231343141 的值为
C
,因为模块 0x23113 尚未被评估13。
B
和
B
时
undefined
的值不会是 0x251812231343144?
C
的主体,然后才能执行模块
C
和
A
的主体。)
最佳答案
答案是使用“init 函数”。作为引用,请看从这里开始的两条消息:https://esdiscuss.org/topic/how-to-solve-this-basic-es6-module-circular-dependency-problem#content-21
解决方案如下所示:
// --- Module A
import C, {initC} from './c';
initC();
console.log('Module A', C)
class A extends C {
// ...
}
export {A as default}
// --- Module B
import C, {initC} from './c';
initC();
console.log('Module B', C)
class B extends C {
// ...
}
export {B as default}
// --- Module C
import A from './a'
import B from './b'
var C;
export function initC(){
if (C) return;
C = class C {
constructor() {
console.log(A)
console.log(B)
}
}
}
initC();
export {C as default}; // IMPORTANT: not `export default C;` !!
// --- Entrypoint
import A from './A'
console.log('Entrypoint', new A) // runs the console.logs in the C
constructor.
var
一样被提升(可能很奇怪,你可以在 esdiscuss 中询问以了解更多信息),但提升是跨模块发生的。类不能被提升,但函数可以(就像它们在正常的 ES6 之前的范围内,但跨模块因为导出是实时绑定(bind),可能在它们被评估之前到达其他模块,几乎好像有一个范围包含所有标识符只能通过使用
import
访问的模块)。
A
导入,模块从模块
C
导入,模块从模块
B
导入。这意味着模块
B
将模块
C
之前评估,但由于这样的事实,所述从模块
initC
导出
C
功能悬挂,模块
B
将给予这个引用悬挂
initC
功能,和模块
B
之前因此模块
initC
调用调用
C
被评估。
var C
的
C
变量在
class B extends C
定义之前被定义。魔法!
C
必须使用
var C
,而不是
const
或
let
,否则理论上应该会在真正的 ES6 环境中抛出时间死区错误。例如,如果模块 C 看起来像
// --- Module C
import A from './a'
import B from './b'
let C;
export function initC(){
if (C) return;
C = class C {
constructor() {
console.log(A)
console.log(B)
}
}
}
initC();
export {C as default}; // IMPORTANT: not `export default C;` !!
B
调用
initC
,就会抛出错误,模块评估将失败。
var
被提升到模块
C
的范围内,因此在调用
initC
时可用。这是一个很好的例子,说明了在 ES6+ 环境中您实际上想要使用
var
而不是
let
或
const
的原因。
let C = C
的黑客可以在某些环境中使用,如上面指向 Meteor 问题的链接中指出的那样。
export default C
和
export {C as default}
之间的区别。第一个版本不会将
C
变量从模块
C
导出为实时绑定(bind),而是按值导出。所以,当
export default C
使用,的
var C
值为
undefined
和将被分配到一个新的变量
var default
被隐藏在ES6模块范围内,并且由于其
C
被分配到
default
(如在
var default = C
由值,则实际上每当模块
C
的默认导出被另一个模块进行访问(例如模块
B
)的其他模块将被到达入模块
C
和访问它总是要
default
所述的
undefined
变量的值。因此,如果模块
C
用途
export default C
,那么,即使模块
B
调用
initC
(这会改变模块
C
的内部
C
变量的值),模块
B
实际上不会访问该内部变量
C
,它将被访问
default
VA riable,它仍然是
undefined
。
C
使用形式
export {C as default}
时,ES6 模块系统使用
C
变量作为默认导出变量,而不是创建一个新的内部 0x2518112431343 变量。这意味着
default
变量是一个实时绑定(bind)。任何时候评估依赖于模块
C
的模块时,都会在给定时刻为模块
C
的内部变量
C
赋值,不是按值,而是几乎像将变量移交给另一个模块一样。因此,当模块
C
调用
B
时,模块
initC
的内部
C
变量被修改,并且模块 02314 使用不同的标识符(因为它具有相同的局部标识符),因为它具有相同的局部标识符基本上,在模块评估期间的任何时候,当一个模块将使用它从另一个模块导入的标识符时,模块系统就会进入另一个模块并及时获取该值。
C
和
B
之间的区别,并且在许多情况下他们不需要,但重要的是要知道在具有“init 函数”的模块之间使用“实时绑定(bind)”时的区别,以便解决循环依赖,以及实时绑定(bind)可能有用的其他问题。不要钻研太远的话题,但是如果您有一个单例,则可以使用事件绑定(bind)作为使模块范围成为单例对象的一种方式,并且事件绑定(bind)是访问单例中事物的方式。
export default C
和
export {C as default}
可能看起来像描述“实时绑定(bind)”的方式:
// --- Module B
initC()
console.log('Module B', C)
class B extends C {
// ...
}
// --- Module C
var C
function initC() {
if (C) return
C = class C {
constructor() {
console.log(A)
console.log(B)
}
}
}
initC()
B
和
C
被跨模块悬挂,所以模块
var C
能够调用
function initC
然后用
B
向右走,
initC
之前和
C
在遇到评估的代码。
var C
有
function initC
,那么
B
仍然是一个容易绑定(bind)到 0x2518122231343141 的模块,但是使用这个变量很容易,但是使用 0x2518122223131313133131313131313131313 变量在前面的例子中,实际上是
Rollup isn't always handling it properly 。
import Blah from './c'
如下,模块
Blah
和
C
是相同的:
// --- Module B
import Blah, {initC} from './c';
initC();
console.log('Module B', Blah)
class B extends Blah {
// ...
}
export {B as default}
C
和
B
发生的情况,结果将如下所示:
// --- Module B
initC()
console.log('Module B', Blah)
class B extends Blah {
// ...
}
// --- Module C
var C
var Blah // needs to be added
function initC() {
if (C) return
C = class C {
constructor() {
console.log(A)
console.log(B)
}
}
Blah = C // needs to be added
}
initC()
A
也有
C
函数调用。这是为了防止模块
B
首先被评估,然后初始化它不会有什么坏处。
C
和
C
在模块评估时依赖于
initC
,而不是在运行时。当模块
C
和
A
被评估时,需要定义
B
导出。但是,当评估模块
C
时,它不依赖于定义的
A
和
B
导入。模块
C
将只需要在 future 运行时使用
C
和
A
,在所有模块都被评估后,例如当入口点运行时 0x25181223134513431343131313431313134313131313131313131314313131431313143131313131313143131431313131431313131313131313143131313143143143143143143143143143123131313131313131313131313131313131313131313都被评估后,所有模块都需要在运行时使用。正是因为这个原因,模块
B
不需要
C
或
A
函数。
B
在定义
new A()
之前的模块评估时间内想要
C
:
// --- Module C
import A from './a'
import B from './b'
var C;
console.log(A)
export function initC(){
if (C) return;
C = class C {
constructor() {
console.log(A)
console.log(B)
}
}
}
initC();
export {C as default}; // IMPORTANT: not `export default C;` !!
C
,因此
initA
模块将在
initB
模块之前进行评估。这意味着模块
C
顶部的
console.log(A)
语句将记录
class C
,因为
A
尚未定义。
C
而不是
A
,整个示例变得更加复杂(我省略了模块 B 和入口点,因为它们没有改变):
// --- Module A
import C, {initC} from './c';
initC();
console.log('Module A', C)
var A
export function initA() {
if (A) return
initC()
A = class A extends C {
// ...
}
}
initA()
export {A as default} // IMPORTANT: not `export default A;` !!
// --- Module C
import A, {initA} from './a'
import B from './b'
initA()
var C;
console.log(A) // class A, not undefined!
export function initC(){
if (C) return;
C = class C {
constructor() {
console.log(A)
console.log(B)
}
}
}
initC();
export {C as default}; // IMPORTANT: not `export default C;` !!
console.log(A)
想在评估期间使用
C
,事情会变得更加复杂,但我把这个解决方案留给你想象......
关于javascript - 如何修复这个 ES6 模块循环依赖?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38841469/
我最近在我的机器上安装了 cx_Oracle 模块,以便连接到远程 Oracle 数据库服务器。 (我身边没有 Oracle 客户端)。 Python:版本 2.7 x86 Oracle:版本 11.
我想从 python timeit 模块检查打印以下内容需要多少时间,如何打印, import timeit x = [x for x in range(10000)] timeit.timeit("
我盯着 vs 代码编辑器上的 java 脚本编码,当我尝试将外部模块包含到我的项目中时,代码编辑器提出了这样的建议 -->(文件是 CommonJS 模块;它可能会转换为 ES6 模块。 )..有什么
我有一个 Node 应用程序,我想在标准 ES6 模块格式中使用(即 "type": "module" in the package.json ,并始终使用 import 和 export)而不转译为
我正在学习将 BlueprintJS 合并到我的 React 网络应用程序中,并且在加载某些 CSS 模块时遇到了很多麻烦。 我已经安装了 npm install @blueprintjs/core和
我需要重构一堆具有这样的调用的文件 define(['module1','module2','module3' etc...], function(a, b, c etc...) { //bun
我是 Angular 的新手,正在学习各种教程(Codecademy、thinkster.io 等),并且已经看到了声明应用程序容器的两种方法。首先: var app = angular.module
我正在尝试将 OUnit 与 OCaml 一起使用。 单元代码源码(unit.ml)如下: open OUnit let empty_list = [] let list_a = [1;2;3] le
我在 Angular 1.x 应用程序中使用 webpack 和 ES6 模块。在我设置的 webpack.config 中: resolve: { alias: { 'angular':
internal/modules/cjs/loader.js:750 return process.dlopen(module, path.toNamespacedPath(filename));
在本教程中,您将借助示例了解 JavaScript 中的模块。 随着我们的程序变得越来越大,它可能包含许多行代码。您可以使用模块根据功能将代码分隔在单独的文件中,而不是将所有内容都放在一个文件
我想知道是否可以将此代码更改为仅调用 MyModule.RED 而不是 MyModule.COLORS.RED。我尝试将 mod 设置为变量来存储颜色,但似乎不起作用。难道是我方法不对? (funct
我有以下代码。它是一个 JavaScript 模块。 (function() { // Object var Cahootsy; Cahootsy = { hello:
关闭。这个问题是 opinion-based 。它目前不接受答案。 想要改进这个问题?更新问题,以便 editing this post 可以用事实和引文来回答它。 关闭 2 年前。 Improve
从用户的角度来看,一个模块能够通过 require 加载并返回一个 table,模块导出的接口都被定义在此 table 中(此 table 被作为一个 namespace)。所有的标准库都是模块。标
Ruby的模块非常类似类,除了: 模块不可以有实体 模块不可以有子类 模块由module...end定义. 实际上...模块的'模块类'是'类的类'这个类的父类.搞懂了吗?不懂?让我们继续看
我有一个脚本,它从 CLI 获取 3 个输入变量并将其分别插入到 3 个变量: GetOptions("old_path=s" => \$old_path, "var=s" =
我有一个简单的 python 包,其目录结构如下: wibble | |-----foo | |----ping.py | |-----bar | |----pong.py 简单的
这种语法会非常有用——这不起作用有什么原因吗?谢谢! module Foo = { let bar: string = "bar" }; let bar = Foo.bar; /* works *
我想运行一个命令: - name: install pip shell: "python {"changed": true, "cmd": "python <(curl https://boot
我是一名优秀的程序员,十分优秀!