skip to content

In a JavaScript class, what is the difference between `super(...)` and `super.someMethod()`, and where is each one allowed to appear?

level: juniorimportance: must knowfreq 72%

answer

  1. one constructs, one looks up
  2. only one place accepts the call form
  3. the receiver stays the current instance
  4. this.method() inside an override recurses
  5. statics have their own parent link

basics

~20 s

super(...) invokes the parent constructor and is legal only inside the constructor of a class written with extends. super.someMethod() calls the parent's version of a method with the current instance as this, and is legal in any method or accessor.

solid answer

~40 s

They are two different syntactic forms that happen to share a keyword. `super(...)` is the **super call**: it runs the parent constructor and initialises `this`. It is legal in exactly one place — the constructor of a class declared with `extends` — and writing it in a base class constructor or an ordinary function is a `SyntaxError`. `super.someMethod()` is a **super property access**: it looks the name up starting from the parent, then calls it with the current `this` still bound, which is how an override wraps the behaviour it is replacing. That form is legal in any concise method, getter, setter or static method, including in a class with no parent at all, where it simply reaches `Object.prototype`. You cannot use either form in a function expression assigned to a property.

code

javascript · 14 lines
javascript
class Animal {
  constructor(name) { this.name = name; }
  speak() { return `${this.name} makes a sound`; }
}
class Dog extends Animal {
  constructor(name) {
    super(name);      // the super call: runs Animal's constructor
    this.legs = 4;
  }
  speak() {
    return super.speak() + ' (a bark)'; // the super property
  }
}
console.log(new Dog('Rex').speak()); // Rex makes a sound (a bark)

go deeper

for a junior

Be able to write both forms correctly: super(args) first in a subclass constructor, and super.method() inside an override to reuse the parent's behaviour without recursing.

for a middle

Explain the legality rules — the call form only in a derived constructor, the property form in any method definition including statics and parentless classes — and why the receiver stays the current instance.

for a senior

Bring the failure modes: infinite recursion from this.method() in an override, SyntaxError in function expressions, and why super.x before super() in a constructor still throws.

for a principal

Discuss when a base class should expect subclasses to chain through super at all, since a required super call in an overridable method is an unenforceable contract that makes the base class fragile.

## One keyword, two forms The grammar treats `super` as two separate productions, and the rules differ for each. ### The super call: `super(...)` This one constructs. It finds the parent constructor — the prototype of the constructor currently running — invokes it, and binds the resulting object as `this` in the derived constructor. It is a statement about *object creation*, so it is legal in exactly one position: inside the constructor of a class declared with `extends`. ```js class Animal { constructor(name) { this.name = name; } } class Dog extends Animal { constructor(name) { super(name); // runs Animal's constructor this.legs = 4; } } ``` Everywhere else it is a `SyntaxError`, caught before the code runs: - in the constructor of a class with no `extends` clause; - in a normal method, even of a derived class; - in a standalone function. If a derived class declares no constructor, the engine supplies `constructor(...args) { super(...args); }`, so the call still happens — you just did not write it. ### The super property: `super.x` This one looks up. `super.speak()` starts the search at the parent of the object the method was defined in, finds `speak` there, and calls it with the current `this`. That last part is the whole point: the parent's code runs against the current instance, so it sees the subclass's own state. ```js class Animal { speak() { return `${this.name} makes a sound`; } } class Dog extends Animal { speak() { return super.speak() + ' (a bark)'; } } new Dog(); // this.name inside Animal#speak is the Dog's name ``` Without it, calling `this.speak()` inside the override would call the override again and recurse until the stack overflows — a classic first-week bug. The property form is legal much more widely than the call form: - instance methods, getters and setters; - static methods, where it reaches the parent **class**'s statics rather than the parent's prototype; - concise methods of ordinary object literals, not only classes; - a class with no `extends` at all, where the parent is `Object.prototype`, so `super.toString()` works. It is also **not** limited to reading. `super.x = 1` performs a set that starts its lookup on the parent — relevant when the parent defines a setter — though the property lands on `this`, not on the parent. ### Where neither form works Both forms need the surrounding function to be a *method definition*. A function expression assigned to a property is not one: ```js const obj = { greet: function () { return super.greet(); } }; // SyntaxError ``` An arrow function is a special case for the property form: it has no `super` of its own but inherits the enclosing method's, so `super.speak()` inside a callback written as an arrow inside a method is fine. ## The ordering interaction The two forms meet in one place. Because `super.x()` calls the parent method with `this` as receiver, and `this` does not exist before the super call, a derived constructor cannot use the property form before the call form: ```js class Dog extends Animal { constructor(name) { super.speak(); // ReferenceError: this is not initialised yet super(name); } } ``` So the ordering rule you learn for `super(...)` also constrains `super.x` inside constructors. ## How to answer this crisply Say: "`super(...)` runs the parent constructor and only exists in a derived constructor; `super.method()` calls the parent's version of a method with the current `this` and works in any method, including static ones and even in a class with no parent." Then give the recursion example — `this.speak()` versus `super.speak()` inside an override — because it shows you know *why* the property form exists rather than just where it is legal.

  • What happens if an overriding method calls this.someMethod() instead of super.someMethod()?
    It calls itself. Property lookup on `this` finds the subclass's own override first, so the method re-enters immediately and blows the stack with a `RangeError`. `super.someMethod()` exists precisely to start the lookup one level above the defining class, so the parent's implementation runs against the same instance.
  • Is super.toString() legal in a class that has no extends clause?
    Yes. The property form only needs a parent to look up on, and for a class without `extends` the instance methods' home object is the class's `.prototype`, whose prototype is `Object.prototype`. So `super.toString()` reaches the built-in implementation. Only the super *call* form requires an `extends` clause; writing `super()` in a base constructor is a `SyntaxError`.
  • What does super refer to inside a static method?
    The parent class object, not its prototype. `extends` sets the subclass constructor's own prototype to the parent constructor, so a static method's `super.create()` finds the parent's static `create` and calls it with `this` still bound to whichever class the call went through — which is what makes inherited static factory methods produce the right subclass.

saying these in an interview costs you the question

  • Says super() can be called from any method
  • Thinks this.method() inside an override calls the parent
  • Believes super.method() runs with the parent as this
  • Claims super is unavailable in a class without extends
  • Assumes super works inside any function in a class body

context