Derived Constructor Without super()

ID

javascript.constructor_super

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

reliability, suspicious-control-flow

Description

Reports an explicit constructor in a class that uses extends but never calls super(…​) in its body. ECMAScript requires every derived-class constructor to invoke the super-class constructor before referencing this or returning normally; if it does not, the JavaScript engine throws ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor.

This is a v1 implementation: a single visible super(…​) call anywhere in the body — even inside a conditional — is enough to satisfy the rule. Calls inside nested function or class bodies do not count, because they belong to a different function scope.

The inverse case (a non-derived constructor that calls super()) is intentionally out of scope here; it is covered by a separate rule.

Rationale

  • Forgetting super() in a derived class is a hard runtime error, not a stylistic issue. The error is masked when the failing path is rarely exercised in tests.

  • Implicit constructors (no constructor() { …​ } declared) are safe — the engine generates constructor(…​args) { super(…​args); } for you.

  • A super() placed inside an inner closure is not a real super-call from the constructor’s point of view; readers may be misled into thinking the rule is satisfied.

// Bad
class Greeter extends Base {
  constructor(name) {
    this.name = name;            // ReferenceError before super() runs
  }
}

// Bad: super() inside an inner function does not count
class Wrapper extends Base {
  constructor() {
    const init = () => { super(); };
    init();                      // syntax error in real JS, and even if it parsed,
                                 // the call would not satisfy the constructor itself
  }
}

Remediation

Call super(…​) from the constructor body — either unconditionally at the top, or in every reachable branch.

// Good
class Greeter extends Base {
  constructor(name) {
    super();
    this.name = name;
  }
}

If the derived class does not need any constructor logic of its own, drop the explicit constructor entirely and rely on the implicit constructor(…​args) { super(…​args); }.