问题描述
我在说:
class MyAction {
}
class MyActionEdit extends MyActionNew { // <-- error pointing here
}
class MyActionNew extends MyAction {
}
我遇到以下错误:Uncaught ReferenceError: Cannot access 'MyActionNew' before initialization.
在加载所有js之前,我没有创建实例。所以我不明白,为什么吊装在这里不起作用。问题是:我无法更改类定义的顺序(它们从各种文件加载并组合成一个大脚本-在此示例中为3个组合文件)。
我已经阅读了这个问题以及许多其他问题,但是没有一个回答我的问题。
例如,这在工作:
class MyAction {
}
let test: MyActionNew = new MyActionNew(); // <- Hoisting works here
class MyActionEdit extends MyAction {
}
class MyActionNew extends MyAction {
}
我该如何处理?我不知道这是否有帮助,但是我正在使用Typescript生成javascript文件。可能有东西吗?
相关: Typescript class: will class be hoisted when I use two classes?
我已经在stackoverflow上阅读了所有带有标签“提升”的问题,但是没有找到答案。
解决方法
未悬挂JavaScript类。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
,在相关链接中是Hero类的示例。在stackoverflow中,有许多答案可以说明,类已悬挂,并且此行为在ES5和ES6之间发生了变化。看看这个答案:Why are ES6 classes not hoisted?
是,但不是。正确地悬挂了类名称 。但是,这与您的情况无关。
JavaScript分两个步骤执行:
- 解析/编译
- 运行时
在解析步骤中,JavaScript引擎将您的代码拆开,读取,标记化,然后通常将其转换为可执行形式。在此步骤中,它列出了将在运行时使用的常规结构,其中包括事物的名称及其所属的范围。因此,将在正确的范围内创建名称 MyActionEdit
。那就是起吊。因为在第二步中,运行时实际上在代码运行时,即使该名称后来出现在范围中,该名称也已经存在:
console.log(foo);
var foo = 'bar';
执行方式如下:
- 解析
var foo
并创建一个保留该名称的作用域。 - 运行时:执行
console.log(foo)
,然后然后执行foo = 'bar'
。
这就是为什么此不会引发错误以及为什么它记录undefined
的原因。这就是“吊装”。
现在,在解析期间还可以完整定义类。 parse步骤创建类。如果该解析步骤成功,则这些类已经“悬挂”并且可以在运行时使用。*但这无关紧要,因为在解析期间声明的顺序是错误的,并且Javascript无法extend
没有该类的类。还没有宣布。它将不得不忽略该第一个类声明,跳到下一个类声明,然后重复分析过程以声明先前跳过的声明。这可能导致无限循环,并且通常效率极低。或者,如果可以先“吊装”课程,应该按什么顺序吊装它们?引擎应该如何知道如何按照需要使类声明具有逻辑意义的顺序来提升类声明?
由您决定以正确的顺序声明类。
*除非在声明之前无法访问它们,因为这种举升行为被认为令人困惑,并且被TDZ明确抑制。