4

I understand based on this stackoverflow post that we need to call super if you're wanting to use this in the subclass and add additional code for it. However, would we need to call make a new constructor and use super still if there's nothing else done?

class SpecialCart extends Cart {

  // Is this constructor really necessary?
  constructor(name){
    super(name); 
  }

  // other methods go here....

}
Community
  • 1
  • 1
ayjay
  • 1,272
  • 2
  • 16
  • 25

2 Answers2

4

No, if you omit the constructor in a class, it will be generated automatically:

constructor( ) { } // for classes without `extends`
constructor(...args) { super(...args); } // for classes with `extends`

The relevant part of the specification can be found here:

ClassTail : ClassHeritageopt { ClassBodyopt }

If constructor is empty, then if ClassHeritageopt is present, let constructor be the result of parsing the source text constructor(... args){ super (...args);}

vaultah
  • 44,105
  • 12
  • 114
  • 143
  • 2
    And if there's no `extends`, it'll just be `constructor() { }` (same spec section). I for one find it interesting that the default when there's an `extends` doesn't have a `return` (e.g., it isn't `return super(...args);`), even though you *can* return something out of a constructor to override the usual result of the `new` operator. – T.J. Crowder Mar 06 '16 at 15:01
  • @T.J.Crowder The value returned from the parent `[[Construct]]` is used to initialize the `this` binding in the child `constructor` when you call `super()`, and if you don't explicitly return anything, the value of `this` is the child constructor's final constructed value, so it should behave the same whether or not you explicitly return. – loganfsmyth Mar 06 '16 at 18:40
  • @loganfsmyth: That's my point: If you explicitly return something else, *that's* the result of the `new` operation, not the ref to the object created by `new`. That's been the behavior of `new` and constructor functions since JS1 and I couldn't find anything in the spec changing it for `class` constructors. So I tried it: Babel doesn't flag up an issue and Chrome allows the altered return value. It has some very strange effects: https://jsfiddle.net/ugxnm5ub/ which aren't quite the same as with old constructors: https://jsfiddle.net/sbarfa8L/ I'm going to have to look at that more deeply. :-) – T.J. Crowder Mar 07 '16 at 07:27
  • Yup! It's definitely an interesting difference from non-class constructors. It is these changes to the `[[Construct]]` process in ES6 that allow extending from builtin types. There _is_ no "object created by new" until you call super, and super is free to create whatever object it likes, and whether that has the expected properties or prototype is up to the constructor. – loganfsmyth Mar 07 '16 at 08:13
0

This is very easy to test by just running the code in an environment that supports classes:

class Base {
  constructor (x) {
    console.log('Base constructor called', x);
  }
}

class TestA extends Base {}

class TestB extends Base {
  constructor (x) {
    super(x);
  }
}

new TestA('a');
new TestB('b');

This results in the following output:

Base constructor called a
Base constructor called b

So yes, when you do not specify the constructor for the inheriting type, the base’s constructor is automatically called. Of course, if you want to have a different signature, or want to perform some other tasks, you will have to implement your own constructor for the inheriting type, and then also make a super() call in order to have the base’s constructor be executed.

This is also formalized in the specification:

  1. If constructor is empty, then,

    1. If ClassHeritageopt is present, then

      1. Let constructor be the result of parsing the source text

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

        using the syntactic grammar with the goal symbol MethodDefinition.

    2. Else,

      1. Let constructor be the result of parsing the source text

        constructor( ){ }
        

        using the syntactic grammar with the goal symbol MethodDefinition.

poke
  • 369,085
  • 72
  • 557
  • 602