子 class 中的字段初始化发生在构造函数在父 class 中完成后,在 javascript 中。这是设计使然吗?
Field initialization in a sub-class happens after constructor finishes in the parent class, in javascript. Is this by design?
展示比描述更容易。这是代码
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()
表示this.Field
等于0,即Bclass中的字段初始化是在A构造函数完成后进行的。这是 "by design" 中的 Javascript 吗?
如果我将 Field
放在 B class 的原型中,那么一切正常,就像在任何其他语言中一样。例如
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:
When field initializers are evaluated...
Base class: At the beginning of the constructor execution...
Derived class: Right after super() returns...
插图:
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 将是正确的地方。
展示比描述更容易。这是代码
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()
表示this.Field
等于0,即Bclass中的字段初始化是在A构造函数完成后进行的。这是 "by design" 中的 Javascript 吗?
如果我将 Field
放在 B class 的原型中,那么一切正常,就像在任何其他语言中一样。例如
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:
When field initializers are evaluated...
Base class: At the beginning of the constructor execution...
Derived class: Right after super() returns...
插图:
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 将是正确的地方。