javascript Typescript -无法通过Object.keys()访问子类中的属性

pkbketx9  于 2023-02-07  发布在  Java
关注(0)|答案(2)|浏览(172)

我尝试对所有子类使用基类构造函数中声明的相同逻辑。更详细地说,我想从它的构造函数中迭代所有类属性。
我的期望是,如果我在基构造函数中调用Object.keys()并在child的构造函数中调用super(),它将为我工作。
代码示例:

class BaseClass {
    private baseField1: string;
    private baseField2: string;

    constructor(data: any) {
        console.log(this.constructor.name + " has fields: " + Object.keys(this));
    }
}

class ChildClass extends BaseClass {
    private childField1: string;

    constructor(data: any) {
        super(data);
    }
}

let base = new ChildClass({name: 'Joe'});

我希望输出:* * 子类具有字段:基本字段1、基本字段2、子字段1**
但事实上我有:* * 子类具有字段:基本场1、基本场2**
输出中没有childField1
有什么办法更好地解决这个问题吗?

mum43rcc

mum43rcc1#

问题不在于Object.keys,而在于在构造函数链中调用它的时机。您在父构造函数中编写了对Object.keys的调用,super在子构造函数中调用它 * 在任何子属性初始化之前 *。
你需要记住,那些漂亮的属性声明只是语法上的糖衣,等价于构造函数中的this.propertyName = undefined,这些行在调用super(父构造函数)之后被求值,换句话说,JavaScript解释器真正要做的是:

class BaseClass {
    constructor(data) {
        this.baseField1 = undefined;
        this.baseField2 = undefined
        console.log(this.constructor.name + " has fields: " + Object.keys(this));
    }
}

class ChildClass extends BaseClass {
    constructor(data) {
        BaseClass.call(this, data);
        this.childField1 = undefined // too late !
    }
}

如果在子构造函数 * 中调用 * super()之后调用Object.keys,或者在构造函数之外的任何地方调用Object.keys,它将按预期工作。
但是,如果您的目标是在构造子示例时立即记录子示例的所有属性并从父类继承此行为......我不认为您可以做到,即使使用代理。

afdcj2ne

afdcj2ne2#

constructor(data: any)--这不是OOP,这是伪装的JavaScript坏习惯。
尽可能的明确你的类的接口,让它确切的询问构造函数中需要什么值,而不是一些不透明的对象。

class BaseClass {
  public constructor(
    private baseField1: string,
    private baseField2: string,
  ) {
    // Object.keys(this) is not a good idea if the class has methods
    console.log(this.constructor.name + " has fields: " + Object.keys(this));
  }
}

class ChildClass extends BaseClass {
  public constructor(
    baseField1: string,
    baseField2: string,
    private childField1: string;
  ){
    super(baseField1, baseField2);
  }
}

// The compiler does not allow you to pass only one argument to the constructor
// It ensures the object integrity
let base = new ChildClass('Joe');

相关问题