【问题标题】:Why does super function calls itself constructor?为什么超级函数调用自己的构造函数?
【发布时间】:2021-09-30 22:00:52
【问题描述】:

我从 MDN 中找到了一个关于 super 的示例。我了解到超级函数调用父类的构造函数,以便子类可以继承它的所有属性/方法。但是,在 MDn 的示例中,它调用了子类的构造函数。

<script>
class Rectangle {
  constructor(height, width) {
    this.name = 'Rectangle';
    this.height = height;
    this.width = width;
  }
}
class Square extends Rectangle {
  constructor(length) {
    super(length, length);
    this.name = 'Square';
  }
}
let a = new Square(4);
console.log(JSON.stringify(a));
console.log(a.height);
</script>

所以我们有一个从 Rectangle 扩展而来的 Square 构造函数。我的困惑在于超级函数有两个来自 Square 的参数,但 Square 是 Rectangle 的子类。在 Square 中调用 super 并将 Rectangle 的高度和宽度传递给它,这样 Square 可以从 Rectangle 继承高度和宽度,因为 Square 正在扩展 Rectangle 是否有意义?

【问题讨论】:

  • @jarmod,很抱歉造成混乱。我已经编辑了我的问题,并愿意在这里以任何方式使我的问题更清楚,以便您理解。
  • 您不必调用构造函数来继承方法。只需要执行父类的初始化。
  • Square 是派生自 Rectangle 的类。 Square 构造函数使用 Rectangle 的宽度和高度的长度调用父 Rectangle 类构造函数(因为 Square 是宽度等于其高度的 Rectangle)。 Square 构造函数需要在访问“this”(设置正方形名称时)或从派生构造函数返回之前调用 Rectangle(超级)构造函数,否则将引发 ReferenceError。方形比矩形更具体。 Rectangle 对 Square 一无所知。
  • @jarmod,很好的答案。如果您能解释更多,并将其作为答案发布,我会接受。

标签: javascript class


【解决方案1】:

Square 是派生自 Rectangle 的类。 Square 构造函数调用父 Rectangle 类构造函数,将 Square 的长度作为 Rectangle 的宽度 高度传递。这样做是有意义的,因为 Square 一个 Rectangle,但它是一种特定类型的矩形 - 即宽度等于其高度的矩形。

请注意,Square 比 Rectangle 更具体,而 Rectangle 对 Square 一无所知。

存在 Square 构造函数是因为 Square 是 Rectangle 的特化。正方形有长度(例如,给我画一个长度为 5 的正方形)。它还有一个不同的名称(“方形”与“矩形”)。这意味着 Square 类需要一个构造函数,以便您可以初始化 Square 的特殊之处。

因为您需要一个 Square 构造函数,所以该 Square 构造函数必须调用 Rectangle(超级)构造函数,并且它必须在访问“this”(它在设置正方形名称时执行此操作)或从派生构造函数返回之前执行此操作。这是 JavaScript 语言的要求。如果您不调用超级构造函数,那么您的代码将失败 - 会发生 ReferenceError,如下所示:

ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor

如果您不需要在派生类的构造函数中进行任何特殊初始化,那么您甚至不需要在派生类中声明构造函数。在这种情况下,JavaScript 会在创建派生类的实例时自动为您调用父类构造函数。但是,如果你在派生类中声明了一个构造函数,即使它是空的,也必须调用超级构造函数,否则就会出现前面提到的ReferenceError。

【讨论】:

    【解决方案2】:

    继承会自动发生,您无需为此调用super()

    super() 用于运行父类的构造函数。当您调用new Square(4) 时,这会自动使用length = 4 调用Square 构造函数。但是Rectangle 构造函数需要两个参数,与Square 构造函数的参数不同。 Square的设计就是它是一个高宽相同的矩形,所以Square构造函数可以将这个length参数传递给Rectangle来表达这个想法。

    我们不能反其道而行之,因为一个类可以有很多不同的子类,并且它们之间可以有不同的关系。超类无法调用所有可能的子类构造函数,因为子类可以任意添加。

    【讨论】:

      【解决方案3】:

      在来自 MDN 的示例中,它调用子类的构造函数。

      没有。

      Square […] 中调用super 是否有意义,这样Square 可以从Rectangle 继承高度和宽度,因为Square 正在扩展Rectangle

      这正是正在发生的事情。

      ...并将高度和宽度从Rectangle 传递给它

      小说明:它将一个值(正方形边长)作为高度和宽度传递给 Rectangle

      new Square 构造调用new Rectangle 构造。

      【讨论】:

      • “不,它没有。”不回答我的问题。为什么没有?
      • @Toby 因为Square 调用Rectangle,而Rectangle 是超类而不是子类。您说您已经“了解到超级函数调用父级的构造函数” - 为什么您认为在示例 sn-p 中不是这种情况?
      猜你喜欢
      • 2011-05-30
      • 1970-01-01
      • 1970-01-01
      • 2017-08-29
      • 2021-11-23
      • 1970-01-01
      • 2018-02-28
      • 1970-01-01
      • 2016-07-16
      相关资源
      最近更新 更多