ES6 javascript class inheritance, why we need call to super() from derived class

1.7k views Asked by At

In javascript ES6, in inheritance,
if derived class has constructor, why it is mandatory to call super from derived constructor ?

few failed examples are -:

. Base with constructor but derived not calling super-

 class Base{constructor(){}}
    class Derived{constructor(){}}
    var d = new Derived(); // fails - ReferenceError: this is not defined
2

There are 2 answers

5
T.J. Crowder On

...it seems it is mandatory to have constructor function in base class.

Not really. If you don't provide one, one will be provided for you by the JavaScript engine. So there will always be one (it's mandatory in that sense), but it doesn't have to be coded explicitly.

When you don't define a constructor at all, the default one provided by the JavaScript engine for a base class will look like this:

constructor( ) { }

...and the default one in a derived class will look like this:

constructor(...args) {
    super(...args);
}

The reason your example fails is that Derived has an explicit constructor, but that constructor doesn't call super. You must call super from within Derived's constructor if you explicitly define one.

if derived class has constructor, why it is mandatory to call super from derived constructor ?

Because you are required to give the superclass an opportunity to do any initialization of the new object that it has to do. Otherwise, the superclass can't guarantee that it will work correctly, as it may rely on the initialization done by its constructor.

So either:

  1. Remove your constructor from Derived, making it like your first example so that the JavaScript engine will provide the default constructor, or

  2. Call super from Derived's constructor.

In a comment you asked:

but if base class does not have any constructor it still fails, if a derived class has

The base class always has a constructor, because if you don't provide one (you did in the code in your question), a default is provided. So you still have to call it. While it could have been specified as optional if none of the superclasses had a non-default constructor, that would be adding complexity and making Derived's explicit constructor misleading (no call to super).

There are also some mechanical reasons: this isn't defined until you call super, but you're allowed to do things prior to calling super, so making the call is necessary to handle the mechanics of this in the spec.

1
Pensierinmusica On

It is not mandatory, but if you want to assign properties to the sub-class you need to call super in the constructor so that the JavaScript interpreter knows which properties belong to the parent class and which ones to the sub-class.

Let's make an example.

In this case there are no properties assigned, only methods, so JavaScript automatically uses a default empty constructor.

class Animal {
  move () {
    console.log('moving');
  }
}

class Dog extends Animal {
  bark () {
    console.log('barking');
  }
}

If we want to assign properties to the sub-class though, we need to invoke super:

class Animal {
  move () {
    console.log('moving');
  }
}

class Dog extends Animal {
  constructor (name) {
    super();
    this.name = name;
  }
  bark () {
    console.log('barking');
  }
}

The reason is that otherwise the JavaScript interpreter has no way of knowing whether the argument passed to the sub-class constructor (name) belongs to the parent class or to the sub-class. So it needs the prgrammer to specify it.