javascript - 子类中的字段初始化发生在构造函数在父类中完成之后,在 javascript 中。这是设计使然吗?
问题描述
展示比描述更容易。这是代码
let ns = {};
ns.A = class {
constructor() {
this.Virtual();
}
Virtual() {
}
};
ns.B = class extends ns.A {
constructor() {
super();
alert(this.Field);
}
Field = 0;
Virtual() {
this.Field = 123;
}
}
alert()
表示等于 0。即 B 类中的this.Field
字段初始化是在 A 构造函数完成后执行的。这是Javascript中的“设计”吗?
如果我把它放在Field
B 类的原型中,那么一切正常,就像在任何其他语言中一样。例如
let ns = {};
ns.A = class {
constructor() {
this.Virtual();
}
Virtual() {
}
};
ns.B = class extends ns.A {
constructor() {
super();
alert(this.Field);
}
//Field = 0;
Virtual() {
this.Field = 123;
}
}
ns.B.prototype.Field;
很抱歉在这里打扰您,但我不知道在哪里报告此问题的正确位置。
解决方案
来自https://github.com/tc39/proposal-class-fields#execution-of-initializer-expressions:
当评估字段初始值设定项时...
基类:在构造函数执行的开始...
派生类:就在 super() 返回之后...
插图:
class A {
constructor() {
console.log('A constructor start');
this.Virtual();
console.log('A constructor end');
}
Field = (() => { console.log('A field init'); return 1})()
Virtual() {
}
};
class B extends A {
constructor() {
console.log('B constructor start')
super();
console.log('B constructor end')
}
Field = (() => { console.log('B field init'); return 2})()
Virtual() {
console.log('B virtual')
this.Field = 123;
}
};
console.log(new B())
也就是说,在您的代码中,Field = 0
发生在 之后this.Field = 123
,从而覆盖它。声明的顺序无关紧要。
如果您对此行为有疑问并希望讨论它,https://github.com/tc39/proposal-class-fields/issues将是正确的地方。
推荐阅读
- python - py 调用返回的大小大于分辨率
- javascript - 从众多输入之一中获得最高价值
- android - 是否可以在返回 LiveData 的 Room @DAO 中编写“挂起”函数?
- android - 如何在 xml 中编辑最上面导航栏的颜色?
- python-3.x - 检查点文件的加载方式/位置
- c++ - QQmlEngine retranslate not translating other StackView items
- apache-spark - 不支持重新分区后合并
- java - 片段中的自定义ListView,我需要什么文件?
- typescript - 对类型转换为 TypeScript 类型的变量调用`new`
- python - QTreeView 数据更改信号/插槽实现?