在下面的代码中,基类有四个属性:一个 getter、一个字段和几个打印其他两个属性的方法。
在子类中,基本 getter 可以被另一个 getter 或字段覆盖。但是,基字段只能被其他字段覆盖,而不能被 getter 覆盖。
我对这种二分法感到有点惊讶。我是不是做错了什么?
class A {
get getter() {
return 'A.getter';
}
field = 'A.field';
go() {
console.log(this.constructor.name, 'go', this.getter, this.field);
return this;
}
go2() {
console.log(this.constructor.name, 'go2', this.getter, this.field);
}
}
class B extends A {
getter = 'B.getter';
get field() {
return 'B.field';
}
go2() {
console.log(this.constructor.name, 'go2', this.getter, this.field);
}
}
class C extends A {
get getter() {
return 'C.getter';
}
field = 'C.field';
go2() {
console.log(this.constructor.name, 'go2', this.getter, this.field);
}
}
new A().go().go2();
new B().go().go2();
new C().go().go2();
你没有做错任何事;此行为与 JavaScript 处理类继承和属性重写的方式一致。
重写 Getters:在 JavaScript 中,getters 只是特殊类型的属性,在访问时运行函数。当您使用另一个 getter 或字段覆盖子类中的 getter 时,您实际上是在替换子类中该属性的属性描述符。这就是为什么您可以使用字段或另一个 getter 覆盖 getter。
覆盖字段:字段本质上是在构造函数中初始化的属性。当您尝试使用 getter 覆盖字段时,它不会按预期工作,因为构造函数中的字段初始化将覆盖 getter。这就是为什么字段只能被其他字段有效覆盖的原因。
以下是代码中发生的情况的详细说明:
new A().go().go2();
将打印“A.getter”和“A.field”,因为它是基类的实例。
new B().go().go2();
将为 go()
打印“B.getter”和“A.field”,为 go2()
打印“B.getter”和“B.field”。 getter
被类 B
中的字段覆盖,并且 field
没有被有效覆盖,因为它是 B
中的 getter。
new C().go().go2();
将为 go()
和 go2()
打印“C.getter”和“C.field”。 getter
和 field
都在类 C
中被有效地覆盖。
因此,您观察到的行为与语言的设计是一致的。