2

In ES6 class constructor, why super() should come before accessing this, if not there's an error thrown: Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor.

But before and after calling super(), this always reference the created object. So Why we have to call super() before accessing this, maybe to prevent from accessing uninitialized parent member? Is there more ideas about that?

Sean
  • 323
  • 2
  • 14
  • 2
    Your object isn't "done" until all ancestor constructors have been run, and because JS has no way of knowing what the super constructor call signature is (because JS allows dynamic types _and_ a dynamic number of arguments) you have to put the code in place that calls `super()` (with whatever parameters are necessary) yourself, before you get to use `this`. – Mike 'Pomax' Kamermans Mar 15 '20 at 05:37
  • Does this answer your question? [How to extend a class without having to use super in ES6?](https://stackoverflow.com/questions/31067368/how-to-extend-a-class-without-having-to-use-super-in-es6) – Daniel Bank Mar 15 '20 at 05:37
  • 2
    The `super()` line calls the parent's constructor, so it initializes the parent first and makes sure the child class doesn't modify the parent's `this` context. – Justin Feakes Mar 15 '20 at 05:38
  • the simplest answer is, because that's what javascript requires you to do, it's part of the design of `class`es ... – Jaromanda X Mar 15 '20 at 06:05
  • @JustinFeakes I like your answer, thanks – Sean Mar 15 '20 at 06:11

1 Answers1

3

From here, refer to the below code. Here super() is called to avoid duplicating the constructor parts' that are common between Rectangle and Square.

class Rectangle {
  constructor(height, width) {
    this.name = 'Rectangle';
    this.height = height;
    this.width = width;
  }
  sayName() {
    console.log('Hi, I am a ', this.name + '.');
  }
  get area() {
    return this.height * this.width;
  }
  set area(value) {
    this._area = value;
  }
}

class Square extends Rectangle {
  constructor(length) {
    this.height; // ReferenceError, super needs to be called first!

    // Here, it calls the parent class's constructor with lengths
    // provided for the Rectangle's width and height
    super(length, length);

    // Note: In derived classes, super() must be called before you
    // can use 'this'. Leaving this out will cause a reference error.
    this.name = 'Square';
  }
}

Now, why calling this before super() will result in a ReferenceError? Well, there is no straightforward answer to that question. However, the intuition is that this requirement ensures that a superclass constructor has had a chance to initialize itself before the allocated object is used. This means that if you write a base class, you don't have to worry about subclasses accidentally forgetting to call super() but still invoking methods that assume that initialization has taken place.

Plabon Dutta
  • 6,819
  • 3
  • 29
  • 33