访问父类中的JavaScript类属性

时间:2019-04-02 16:27:07

标签: javascript es6-class

在ES6中有什么可能的方法吗?或者(如果可能)是否有很好的解决方案:

class Parent {
    constructor() {
        console.log(this.name);
    }
}

class Child extends Parent {
     name = "Child Name";
}

const c = new Child();
// Should console.log "Child Name";

(来自Python,完全可以使用!)

5 个答案:

答案 0 :(得分:1)

在子级可以初始化其实例数据之前调用父级的构造函数,因此您不能在父级的构造函数中引用子级的实例。那是错误的OOP设计(至少在Javascript中)。如果父级想要访问构造函数中的属性,则在父级构造函数中定义并初始化该属性(子级仍可以使用它)。

父母不应该依赖子女-子女要依赖父母。

因此,这是有缺陷的OOP设计。您没有显示要解决的实际问题,因此我们无法真正建议针对实际问题的正确设计。


回顾一下,事情的顺序是:

  1. 子构造函数称为
  2. 子构造函数调用super(...)来执行父构造函数
  3. 父构造函数初始化其实例数据
  4. 父级构造函数返回后,子级构造函数有机会初始化其实例数据

如果使用ES6类定义,则无需将此顺序更改为其他内容。


根据您对此答案的最新评论,我认为没有比向每个孩子添加额外的代码行更好的方法了:

class Parent {
    constructor(name) {
        if (!name) {
            // could also throw an exception here if not
            // providing a name is a programming error and is not allowed
            this.name = "Default Name";
        } else {
            this.name = name;
        }
        console.log(this.name);
    }
}

class ChildA extends Parent {
     constructor() {
         super("ChildA Name");
     }
}

class ChildB extends Parent {
     constructor() {
         super("ChildB Name");
     }
}

const c = new ChildA();
// Should console.log "ChildA Name";

答案 1 :(得分:1)

要保留父级的name属性的值,只需将构造函数放在子类之外即可。另外,如果您要更新特定的属性(在这种情况下为name),则需要在构造函数 AFTER 中将this.name设置为对super()的调用-必须先显式调用super(),然后才能设置this属性,否则JavaScript会引发错误。

以下是我在上面尝试解释的一个示例:

class Parent {
  constructor() {
    this.name = "Parent Name";
  }
}

class ChildWithConstructor extends Parent {
  constructor() {
    super();
    this.name = "Child Name";
  }

  sayName() {
    console.log(`The constructor call updated the property value set in the parent contructor: ${this.name}`)
  }
}

class ChildWithoutConstructor extends Parent {
  sayName() {
    console.log(`No constructor call retains the property values set in the parent contructor: ${this.name}`)
  }
}

const c = new ChildWithConstructor();
const nc = new ChildWithoutConstructor();
c.sayName();
nc.sayName();

答案 2 :(得分:1)

唯一的方法是在子构造函数上调用一个名为init的方法,并在父类上进行定义,然后将init方法用作您的父构造函数。

以这种方式在子属性准备就绪时将调用init

class Parent {
    constructor() {
      
    }
    
    init() {
      console.log(this.name);
    }
}

class Child extends Parent {
     name = "Child Name";
     
     constructor() {
      super();

      // call parent init
      this.init();
    }
}

const c = new Child();

答案 3 :(得分:0)

无法从父类访问子类的字段。从孩子到父母-您可以使用 super

    class Parent {    
        constructor() {
          this.name="Parent Name";      
        };
    }

    class Child extends Parent {
      constructor(){
        super(name);
        console.log(this.name);
        this.name = "Child Name";
        console.log(this.name);    
      }
    }

    const c = new Child();

答案 4 :(得分:0)

据我所知,函数应该与属性相反。

属性 - 第一个父级(至少是这个例子)


功能 - 先看看你自己,如果你没有,再看看

class Parent {
  constructor() {
    console.log(this.name());
  }
}

class Child extends Parent {
  name() {
    return "Child Name";
  }
}

const c = new Child();
// Should console.log "Child Name";

如果你想改变,而不是做this.name = 'something'
你可以做一个功能

setName(newName){
  this.name = function(){
    return newName
  }
}

是的,设置新值很难看,我什至不确定是否有效。