1
class Overflow {}
class Stack extends Overflow {
  constructor() {
    super();
  }
}

let stack = new Stack();

https://plnkr.co/edit/JqRfuDAav9opvapwCGpT?p=preview

If I use construtor() I must call super() always.

Why isn't super() auto called in constructor?

Edit: Is super() here calling the base constructor AND setting the prototype? Seems wrong. Edit: Why is super() required? Even when I've no intention of calling the base constructor.

old
  • 31
  • 8
  • *"Why isn't `super()` auto called in constructor?"* Which arguments should be passed to it? None, all or a subset? Any decision would probably lead to a discussion why that approach was chosen and not another... – Felix Kling May 10 '16 at 18:13
  • The call to `super()` is required **always**. Try to write a valid ES6 constructor without `super()`. – old May 10 '16 at 18:24
  • I know... I don't understand what you are trying to tell me with your comment. – Felix Kling May 10 '16 at 18:25
  • *"Why is `super()` required? Even when I've no intention of calling the base constructor."* Because `this` needs to be initialized properly (i.e. the object generated by calling the constructor needs to be constructed properly). That is primarily a concern for extending exotic objects / classes, such as `Array`. – Felix Kling May 10 '16 at 18:26
  • Related: https://esdiscuss.org/topic/not-forcing-super-in-derived-class-s-constructor – Felix Kling May 10 '16 at 18:32
  • @FelixKling Thank you for this link. Really. From this link I read link after link. I had some backgrounds missing. – old May 11 '16 at 13:23
  • My understanding now is: the call to `super()` is required because you **MAY** use the `this` of base class. More like a safety reason. – old May 11 '16 at 13:26
  • BUT, if you don't use `this` at all. Your base class don't need to be a base class, lol. Now I get it. – old May 11 '16 at 13:27
  • Not just that. The whole purpose of `new X()` is to create a new object. The caller will definitely use that object. Having to call `super()` is a guarantee that the base class can initialize that object properly. – Felix Kling May 11 '16 at 13:30
  • Thinking more.. This is just for safety no? I could never call the base constructor in derived, but some base method could set state `this.x = 'x'` (just like other languages). Perhaps not the best practice. – old May 11 '16 at 14:07
  • *"I could never call the base constructor in derived"* If you have a custom `constructor` you have to call `super()`. If you don't have a custom `constructor`, the base constructor will be called automatically. – Felix Kling May 11 '16 at 15:40
  • In the current ES6, yes. But why this? – old May 11 '16 at 15:41
  • https://stackoverflow.com/questions/37144920/es6-super-required-in-constructor?noredirect=1#comment61830517_37144920 – Felix Kling May 11 '16 at 15:42
  • This was a spec for the keyword `class`. The old way, in ES5, can allow you to call the "construtor" without calling the base one. Why this is the standard in a sugar syntax? – old May 11 '16 at 15:48
  • In ES5 it wasn't possible to extend exotic objects like `Array`. As I said, this enforcement is primarily because of exotic objects. In ES5, calling `new X` is basically the same as `X.call(Object.create(X.prototype))`, i.e. it would simply generate a generic object and pass that to the constructor. But arrays are not simply objects and they cannot be created before the constructor function is called (because it is not known at that moment how exactly to create them). Hence it has to be done inside the constructor itself, via `super()`. – Felix Kling May 11 '16 at 15:50
  • http://stackoverflow.com/a/28224044/4341575 – old May 11 '16 at 16:58

2 Answers2

4

Why isn't super() auto called in constructor?

So you can decide where in the constructor to call it. This is perfectly valid, for instance:

constructor(foo) {
    let bar;
    if (foo) {
        bar = /*...*/;
    } else {
        bar = /*...*/;
    }
    super(bar);
}

...provided no code prior to the call to super uses this (or super.xyz).

Yes, it would have been possible to define the language such that if you didn't have any call to super in your constructor at all, it was added automatically for you at the beginning (a'la Java), but they just decided not to do it that way.

Is super() here calling the base constructor AND setting the prototype? Seems wrong.

No, it's calling the base constructor. The prototype was set before your constructor was called. It's exactly like this old ES5 code:

function Derived() {
    Base.call(this);
}

...in:

function Base() {
}

function Derived() {
    Base.call(this);
}
Derived.prototype = Object.create(Base.prototype);
Derived.prototype.constructor = Derived;

Why is super() required? Even when I've no intention of calling the base constructor.

If you have no intention of calling the base constructor, then your subclass isn't a subclass and shouldn't be extending the base. In a strictly-typed language you'd probably make the base (or a subset of the base) an interface and have your class implement that rather than subclassing. In JavaScript, no need, just make it quack like the duck you want it to be. If an instanceof relationship is important, create a new base that will act like an interface but doesn't do anything anywhere, and have the old base and your class subclass it directly.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Is `super()` here calling the base `constructor()` AND setting the prototype? Seems wrong that I'm required to call a `super()` I didn't asked. – old May 10 '16 at 17:19
  • Perhaps my question is more towards to **why** calling the `super()` is required. – old May 10 '16 at 17:36
  • It isn't strictly required. You could also `return` something, so if it auto-added `super()` at the beginning, you'd be doing extra work. It's also not quite exactly like the ES5 code though, as `this` is uninitialized until you've called `super()` so there isn't even an object to have a prototype yet. – loganfsmyth May 10 '16 at 17:56
  • @old: It is required to correctly initialize `this`. If you think it should be called implicitly, which arguments should be passed to it? – Felix Kling May 10 '16 at 18:11
1

Axel FTW http://www.2ality.com/2015/02/es6-classes-final.html

Summary

Why super is required?

  • The new keyword class isn't just syntax sugar.
  • Allocation and instantiation only happens in the base constructor.

But why this?

  • To allow exotic objects to be extended (thank you Felix Kling).
old
  • 31
  • 8