代码之家  ›  专栏  ›  技术社区  ›  Daniel Lizik

重写父类构造函数的子类成员初始值设定项

  •  0
  • Daniel Lizik  · 技术社区  · 2 年前

    如果我有一个超类,它应该能够在一个新实例上设置一些初始属性,为什么子类的成员似乎覆盖了超类的构造函数?

    class Base {
      constructor(fields) {
        Object.assign(this, fields)
      }
    }
    
    class Foo extends Base {
      time = 0;
      
      // calling super seems to make no difference
      // constructor(...args) {
      //  super(...args)
      // }
    }
    
    const foo = new Foo({ time: 22 })
    
    console.log(foo.time) // is 0, should be 22?

    如果我移除 time = 0; 从儿童课上看,它像预期的那样工作,但我的绒线断了。

    如何保留成员初始值设定项,即。, 时间=0; 在子类中,但超类是否能够在其构造函数中设置属性?

    1 回复  |  直到 2 年前
        1
  •  1
  •   CertainPerformance    2 年前

    实例只能在 super 通话结束。如果没有class字段,请查看错误:

    class Base {
      constructor(fields) {
        Object.assign(this, fields)
      }
    }
    
    class Foo extends Base {
      constructor(...args) {
        this.time = 0;
        super(...args)
      }
    }
    
    const foo = new Foo({ time: 22 })

    在访问“this”或从派生构造函数返回之前,必须在派生类中调用超级构造函数

    类字段遵循同样的逻辑,只在超级调用完成后才分配给实例。所以

    class Foo extends Base {
      time = 0;
      
      constructor(...args) {
        super(...args)
    

    相当于

    class Foo extends Base {
      constructor(...args) {
        super(...args)
        this.time = 0;
    

    换句话说,在子类的构造函数(或类字段)中指定的属性 设计 重写在超类构造函数中指定的属性。

    但是,超级类是否能够在其构造函数中设置属性?

    一种方法是使用 time 属性设置为0,然后传递并使用该属性,而不是类字段:

    class Base {
      constructor(fields) {
        Object.assign(this, fields)
      }
    }
    
    class Foo extends Base {
      constructor({ time = 0, ...rest }) {
        super({ time, ...rest })
      }
    }
    
    const foo = new Foo({ time: 22 })
    
    console.log(foo.time)