ReferenceError: super() called twice in derived class constructor

super() 在给定的派生类构造函数中第二次被调用时,会发生 JavaScript 异常 "super() 在派生类构造函数中被调用两次"。

消息

ReferenceError: Super constructor may only be called once (V8-based)
ReferenceError: super() called twice in derived class constructor (Firefox)
ReferenceError: 'super()' can't be called more than once in a constructor. (Safari)

错误类型

ReferenceError

哪里出错了?

对于派生类构造函数的每次 new 调用,super() 最多只能调用一次。这是因为 super() 负责初始化父类,多次调用会导致父构造函数被多次调用。

防止这种情况的最佳方法是确保 super() 放置在任何控制流结构之外。否则,请确保构造函数中的所有代码路径都只导致一次 super() 调用。

super() 调用可以“保存”在构造函数内部嵌套的箭头函数中。然后,当你调用箭头函数时,你也将调用 super(),并且适用相同的规则:箭头函数最多只能被调用一次。

示例

无效案例

js
class Base {}

class Derived extends Base {
  constructor() {
    super();
    super();
  }
}

有时错误可能更隐蔽。

js
class Base {
  constructor(flavor) {
    // Do something with the flavor
  }
}

class Derived extends Base {
  constructor(flavors) {
    if (flavors.includes("chocolate")) {
      super("chocolate");
    }
    if (flavors.includes("vanilla")) {
      super("vanilla");
    }
  }
}

最初,flavors 可能永远不会同时包含“chocolate”和“vanilla”,但如果发生这种情况,构造函数将调用 super() 两次。你需要重新考虑你的类应该如何构建以避免这个问题。

有效情况

js
class Base {}

class Derived extends Base {
  constructor() {
    super();
    // More initialization logic
  }
}

另见