typescript - 属性初始化顺序打字稿
问题描述
我在 Typescript 中有 2 个课程,A 和 B。B 派生自 A,A 的构造函数调用函数init
,B 覆盖init
。a.ts
export default class A {
constructor() {
this.init();
}
init() {
console.log("A.init()")
}
}
b.ts
import A from "./a"
export default class B extends A {
public bx = 3;
public by = 10;
public bz = 0;
constructor() {
super();
}
init(){
this.bx = 5;
this.bz = this.by;
console.log("B.init()")
}
}
编译的js文件tsc
就像
一个.js
export default class A {
constructor() {
this.init();
}
init() {
console.log("A.init()");
}
}
b.js
import A from "./a";
export default class B extends A {
constructor() {
super();
this.bx = 3;
this.by = 10;
this.bz = 0; //even worse
}
init() {
this.bx = 5;
this.bz = this.by;
console.log("B.init()");
}
}
毫无意外a.js
。但是在 中b.js
,我们可以在构造函数的this.bx = 3;
后面看到一行。super()
虽然我同意有必要初始化一个像类this.bx = 3;
中的声明这样的属性,但我根本无法理解为什么在这种情况下,它甚至this.bx=3;
在super()
理论上编译器应该能够知道this.bx
已经设置并且不是从 AST 未初始化. 有什么考虑?如果该属性从未被分配,它应该只初始化一个属性。就我而言,我想应该是
import A from "./a";
export default class B extends A {
constructor() {
super();
}
init() {
this.bx = 3; // initialisation from the declaration can appear here before the first time use. It can be optimized because of the next line assignment
this.bx = 5; // first time use `this.bx`
this.by = 10; // the initialisation here is because this.by is used in the next line
this.bz = this.by;
console.log("B.init()");
}
}
与 c# 比较
using System;
public class Program
{
public static void Main()
{
B b = new B();
Console.Out.Write("x: " + b.x + " y: " + b.y);
}
}
class A {
public A() {
init();
}
public virtual void init() {
}
}
class B : A {
public int x = 3;
public int y = 10;
public int z = 4;
public B() : base() {
}
public override void init() {
this.x = 5;
this.y = this.z;
}
}
你会得到x: 5 y: 4
.
解决方案
有充分的理由确保在扩展子类的初始化发生之前完全初始化您的基类,这是 MDN 文档中规定的super
:
通过让您的基类在其构造函数中调用一个覆盖this
子类的属性的方法,您已经搞乱了初始化的顺序。由于违反了这一重要要求,编译器在此要求背后所做的任何假设现在都被打破了。
混乱随之而来……
这里最可取的结果是一个胖编译错误。
推荐阅读
- html - 使用文本和伪元素旋转 div?
- c++ - C++ uni 任务显示最远城市的最便宜机票
- c# - 光线投射鼠标位置以在 3D 网格上绘制
- javascript - 在 Angular 测试库测试中渲染 html 属性
- javascript - 试图打破这个承诺的例子
- pandas - 在 Python 中读取 TXT 或 DAT 文件
- vba - MS Access -“自从您开始编辑此记录以来,该记录已被其他用户更改”
- authentication - 在 GCP 环境外验证 Google Cloud 函数调用
- javascript - 使用 Ajax 选中复选框
- php - 如何在 laravel 中链接我的产品页面详细信息?