我正在编写代码,遇到了这个场景,我无法理解。
场景如下:我有一个来自我正在扩展的库的类。 这个类是“Parent”类。它允许它的子类覆盖 init 方法以进行自定义初始化。
然而,第二个孩子的表现并不像我想象的那样。这两个类之间的唯一区别是成员变量的声明(?)。当编写纯 JS 时,我什至不会考虑这样做,但我是用 Typescript 编写的,这是编译结果(实际上,我什至没有在我的具体情况下赋值。TS 编译器只包含一个“member; ”并且输出确实显示为“未定义)
我很确定只有当变量设置在父构造函数调用的覆盖函数中时才会出现此问题。
有人可以向我解释为什么会发生这种情况吗?
class Parent {
constructor(initArgs) {
this.init(initArgs);
}
init() {}
}
class ChildTest1 extends Parent {
init(args) {
this.member = args;
}
test() {
console.log(`Member of ChildTest1 has value of "${this.member}"`);
}
}
class ChildTest2 extends Parent {
member = "default";
init(args) {
this.member = args;
}
test() {
console.log(`Member of ChildTest2 has value of "${this.member}"`);
}
}
new ChildTest1("Hello World").test();
new ChildTest2("Hello World").test();
输出以下内容:
ChildTest1 的成员的值为“Hello World”
ChildTest2 的成员的值为“default”
您的变量在初始化期间被覆盖。属性初始化和构造函数执行顺序如下:
父类的构造函数执行并将
member
初始化为 Hello World
您的子类属性已初始化,覆盖先前初始化的成员变量。
您的子类构造函数执行
我已经使您的代码更加明确(请注意,添加子构造函数在功能上与您的示例等效)来演示这一点:
class Parent {
constructor(initArgs) {
this.init(initArgs);
console.log(`Parent Constructor: Member of ChildTest2 has value of "${this.member}"`);
}
init() {}
}
class ChildTest2 extends Parent {
member = "default";
constructor(initArgs) {
super(initArgs);
console.log(`Child Constructor: Member of ChildTest2 has value of "${this.member}"`);
}
init(args) {
this.member = args;
console.log(`Init: Member of ChildTest2 has value of "${this.member}"`);
}
test() {
console.log(`Test: Member of ChildTest2 has value of "${this.member}"`);
}
}
new ChildTest2("Hello World").test();
打印:
[LOG]: "Init: Member of ChildTest2 has value of "Hello World""
[LOG]: "Parent Constructor: Member of ChildTest2 has value of "Hello World""
[LOG]: "Child Constructor: Member of ChildTest2 has value of "default""
[LOG]: "Test: Member of ChildTest2 has value of "default""
作为心理模型,您可以假设类属性初始化发生在构造函数内的
super(...)
调用之后。更多相关内容这里
设置 tsconfig
"useDefineForClassFields": false,
它将帮助我们