ReferenceError: 在派生类构造函数中调用 super() 两次

当对给定的派生类构造函数第二次调用 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)

错误类型

哪里错了?

对于每次对派生类构造函数的 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
  }
}

另请参阅