为什么不能访问具有相同名称的父类属性?

时间:2019-10-29 20:59:24

标签: javascript node.js

我在Java语言中有两个类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 and I AM A,但我得到I AM A and I AM A。我也尝试过super.speakB() + " and " + this.name;,但没有成功。

在声明类时是否缺少某些内容?

1 个答案:

答案 0 :(得分:4)

当您用派生类扩展一个类,然后实例化派生类时,那里只有一个对象。无论代码位于哪个类中,this.name都指向该对象的相同this和相同属性。

这里的关键是只有一个对象,基类和派生类都将其设置为属性。因此,如果您使用相同的命名属性,则无论是哪个基类或派生类对其进行设置,其值都将相同。

这样想:

let obj = new A();
obj.name = "Bob";

只有一个对象具有一个.name属性。 A和B的方法都在同一个对象上操作,因此在方法A和B中使用相同的属性名称将设置完全相同的属性。

执行此操作时:

 this.name = "I AM A".

在派生类中,您将覆盖父B为.name属性设置的先前值。

  

这意味着我不能为两个类使用相同的属性名称吗?

正确,如果您希望两个属性具有单独的值,则不正确。注意,在很多情况下,派生类想访问基类设置的属性,因此这也是一个功能。但是,如果您打算将两个属性分别用于基本属性和派生属性,则必须给它们指定不同的名称。


对于某些人来说,一个可能引起混淆的原因是,通过class语法声明的方法对于每个类都是分开的。每个类都有自己的原型对象,并且在链中搜索原型以解析方法。即使基类和派生定义了相同的命名方法,这也允许您专门调用基类方法。

但是,对于常规实例属性分配this.x = "foo"而言,情况并非如此,因为它们是分配给实例对象而不是原型对象的。请记住,原型在所有对象实例之间共享,因此您不能在实例上存储实例状态。