繁体   English   中英

访问父类中的 JavaScript 类属性

[英]Access JavaScript class property in parent 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,它完全可以工作!)

在孩子初始化他们的实例数据之前调用父母的构造函数,因此您不能在父母的构造函数中引用孩子的实例。 那是错误的 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";

要保留父类的name属性的值,您只需将构造函数排除在子类之外。 或者,如果要更新特定属性(在本例中name ),则需要在调用super()之后在构造函数中设置this.name - 在设置this属性之前需要显式调用super() , 否则 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();

唯一的方法是在子构造函数上调用名为 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();

有一个不错的方法
注意this.constructor是类,不管它在哪里执行。
所以我们可以用它来挂数据。

 class Parent{ static prop = "default property" constructor(){ console.log(this.constructor.name, this.constructor.prop) } } class Child extends Parent{ static prop = "new property" } new Parent() new Child()

类,无法访问类的字段。 从孩子到父母-您可以使用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();

据我所知,功能应该与属性相反。

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


功能——先看你自己,没有就查

 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
  }
}

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

仅用于构造函数

如果该道具仅在构造函数中使用,则作为参数传递。

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

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

对于构造函数和其他方法

如果需要,请使用getterstatic 请参阅@FLAW 的答案。
但是为什么不将构造函数逻辑移至其他方法。 它更简单。

class Parent {
    name = "Parent Name";
    hello() { console.log(this.name); }
}

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

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

// getName() works, too.
class Parent {
    static name = "Parent Name";
    constructor() { console.log(this.constructor.name); }
}

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

如果将类保存在单独的文件中,另一件非常重要的事情是加载顺序。

我有以下 JS 文件:

  • 相机.js
  • 地图.js

地图.js

 class Map {
        constructor() {
            this.tileWidth = 32;
            this.tileHeight = 32;
        }
    }

相机.js

class Camera extends Map
{
    constructor() {
        super();
        
        this.viewPortXTiles = 20;
    }
    
    viewport()
    {
        var viewPortX = this.tileWidth * this.viewPortXTiles;
        
        console.log(this.tileWidth);
    }
}

如果加载顺序首先加载 camera.js,这将返回 undefined。 所以要么把它们放在同一个文件中,要么调用camera.js文件:map_camera.js

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM