我正在学习打字稿中的类概念。我认识到有两种方法可以在打字稿中初始化字段(属性):内联初始化类主体和在构造函数方法内部初始化。我想知道初始化内联和初始化在另一个之前运行的构造函数内部。
我尝试了以下代码来测试,但我仍然不知道哪个先运行。
class Point{
x :number = 0;
y: number = 0;
constructor();
constructor(x:number,y?:number) ;
constructor(x?:number,y?:number) {
if(typeof x =='number') this.x = x;
if(typeof y =='number') this.y = y
}
}
let p = new Point(1);
console.log(`${p.x} ${p.y}`);
代码的结果是:
1 0
我用谷歌搜索了很多并阅读了一些其他问题(在声明期间内联初始化变量与在 Angular 中使用 TS 的构造函数),但我还没有找到答案。
感谢您考虑我的愚蠢问题。
类字段及其行为是 JavaScript 的一部分(从 ES2019 开始),即使您使用的是早期版本,TypeScript 通常也应该downlevel以保持相同的行为。 (这里有一个问题,因为 TypeScript 在 JavaScript 中存在之前就引入了类字段,并且 JavaScript 实现与 TypeScript 的假设有些不同,导致了
--target
编译器标志,但这并没有太大改变这里描述的行为)。 根据文档:“公共实例字段要么在基类的构造时(在构造函数主体运行之前)添加到实例中,要么在 --useDefineForClassFields
在子类中返回之后添加到实例中。”
因此,一般来说:类字段声明上的初始化器发生在构造函数体内的赋值之前。
super()
在这里,我使用
逗号运算符 (class Test {
x: number = (console.log("field declaration"), 1)
constructor() {
this.x = (console.log("constructor body"), 2);
}
}
const t = new Test();
//[LOG]: "field declaration"
//[LOG]: "constructor body"
console.log(t.x)
//[LOG]: 2
)在每次分配之前不久登录到控制台。您可以看到字段声明初始值设定项发生在构造函数赋值之前。
当你创建子类时,超类的东西首先发生,然后是子类的东西,但在这两种情况下,字段声明都发生在构造函数主体的其余部分之前:,
这
可能看起来像一个例外,因为超类构造函数在子类字段声明之前运行,事实上,如果您可以在调用
class SubTest extends Test {
x: number = (console.log("field declaration subclass"), 3);
constructor() {
super();
this.x = (console.log("constructor body subclass"), 4)
}
}
const s = new SubTest();
// [LOG]: "field declaration"
// [LOG]: "constructor body"
// [LOG]: "field declaration subclass"
// [LOG]: "constructor body subclass"
console.log(s.x)
// [LOG]: 4
之前在子类构造函数主体中分配一个属性,那么它将
是一个例外。 但这是被禁止的;在调用
super()
之前,this
基本上不存在:super()
因此:字段声明初始值设定项发生在同一类的构造函数主体中的赋值之前。
Playground 代码链接