我在 Javascript 中有两个类 A 和 B,A 扩展了 B,并且它们在构造函数中都有一个同名的属性。
我试图从 B 类访问属性 name
的值,但在从 A 创建新对象时它被 A 的值替换。
class B {
constructor(){
this.name = "I AM B"
}
speakB(){
return this.name
}
}
class A extends B {
constructor(){
super()
this.name = "I AM A"
}
speakA(){
return this.speakB() + " and " + this.name;
}
}
var b = new B();
console.log(b.speakB()) //I AM B
var a = new A();
console.log(a.speakA()) //I AM A and I AM A
正如预期的结果,我想要得到 I AM B 和 I AM A
,但我得到了 I AM A 和 I AM A
。我还尝试了 super.speakB() + "和 "+ this.name;
但没有成功。
声明类时我遗漏了什么吗?
最佳答案
当您使用派生类扩展一个类,然后实例化该派生类时,那里只有一个对象。无论代码位于哪个类,this.name
都引用该对象上的相同 this
和相同属性。
这里的关键是,基类和派生类都在一个对象上设置属性。因此,如果您使用相同的命名属性,则无论哪个基类或派生类设置它,它都将是相同的值。
这样想:
let obj = new A();
obj.name = "Bob";
只有一个对象具有一个 .name
属性。 A 和 B 的方法都操作同一个对象,因此在方法 A 和 B 中使用相同的属性名称将设置完全相同的属性。
当你这样做时:
this.name = "I AM A".
在派生类中,您将覆盖父级 B 为 .name
属性设置的先前值。
It means that I cannot use the same property name for both classes?
正确,如果您打算让两个属性具有单独的值,则不正确。请注意,在很多情况下,派生类想要访问基类设置的属性,因此这也是一个功能。但是,如果您打算将两个属性的基类属性和派生属性分开,那么您必须为它们指定不同的名称。
一些人可能会感到困惑的一个原因是,通过 class
语法声明的方法对于每个类都是分开的。每个类都有自己的原型(prototype)对象,并且在链中搜索原型(prototype)来解析方法。这确实允许您专门调用基类方法,即使基类和派生类都定义了相同的命名方法。
但是,对于常规实例属性分配 this.x = "foo"
来说,情况并非如此,因为它们被分配给实例对象,而不是原型(prototype)对象。请记住,原型(prototype)在所有对象实例之间共享,因此您无法在原型(prototype)上存储实例状态。
关于javascript - 为什么无法访问父类的同名属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58615359/