【问题标题】:Javascript base class constructor run with subclass (overridden) propertyJavascript 基类构造函数使用子类(覆盖)属性运行
【发布时间】:2021-01-16 09:07:08
【问题描述】:

我在 JS 中使用子类覆盖类属性时遇到了这个问题。我认为 OOP 中的行为是我想要的,但我希望在 JS 中实现同样的效果。

class Base {
   constructor () {
       console.log(this.a)
   }
}

class Child extends Base {
    a = 1
}

new Child()

// undefined, but I expect (want) 1

如何修改我的代码以记录1

Python 中的示例,有效:

class Base:
    def __init__(self):
        print(self.a)
        
class Child(Base):
    a = 1
    
Child()

# 1 -> desirable

【问题讨论】:

  • 可能找到了一个很好的答案javascript.info/…
  • 这是时间问题。您不能在声明之前访问属性,这就是您得到undefined 的原因。而且您不能更改执行顺序,因为在调用super() 之前,您无法在派生构造函数中访问this。因此,要解决这个问题,您需要更具体地说明您想要在基类中做什么,以找到合适的解决方法。

标签: javascript typescript class oop inheritance


【解决方案1】:

undefined 输出是预期行为。您还没有在基类中定义属性a,因此基类构造函数在控制台中输出undefined 是很自然的。

class Base {
   constructor () {
       console.log('Base constructor', this.a) // outputs undefined
   }
}

class Child extends Base {
    a = 1

   constructor () {
      super();
      console.log('Child constructor', this.a); // outputs 1
   }
}

new Child()

更新

在 Python 中,__init__ 函数不是真正的构造函数。构造函数是__new__

【讨论】:

  • 不完全是。如果将方法添加到基类并在构造后调用该方法,则基类可以完全访问该实例上的所有属性(按设计)。 JS 最近刚收到private class fields。在此之前,每个属性都是公开的(闭包是一个单独的主题)。问题在于i=1 的执行位置。它基本上是这样内联的:super(); this.i = 1; console.log('Child constructor', this.a);。所以这不是隐私问题,而是时间问题。
  • 感谢您的回答 - 问题是,我有很多孩子,不想在所有孩子中编写单独的构造函数。很想知道我是否可以做任何快速的黑客攻击
【解决方案2】:

这就是我最终做的:

class Base {
   constructor () {
       console.log(this.a)
   }
}

class Child extends Base {
    get a () { return 1 }
}

new Child()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    • 2020-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-26
    • 1970-01-01
    相关资源
    最近更新 更多