# JS Tip of the Day: super() Defines this

**URL:** <https://forum.kirupa.com/t/js-tip-of-the-day-super-defines-this/643157>\
**Category:** web dev\
**Created:** [March 10, 2020, 12:14pm UTC](https://forum.kirupa.com/t/js-tip-of-the-day-super-defines-this/643157 "2020-03-10T12:14:41Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![senocular](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/senocular/32/7217_2.png) [@senocular](https://forum.kirupa.com/u/senocular)\
**Post date:** [March 10, 2020, 12:14pm UTC](https://forum.kirupa.com/t/js-tip-of-the-day-super-defines-this/643157/1 "2020-03-10T12:14:41Z")

</div>

**super() Defines this**  
Version: ES2015  
Level: Advanced

In function-based constructors, the instance being constructed is created as soon as the constructor is invoked and is immediately accessible through the `this` keyword. If extending another class/constructor, running the superclass constructor is handled by explicitly calling the superclass constructor in the context of that new instance.

```javascript
function Button () {
    this.enabled = true;
}

function ToggleButton () {
    // this instance created
    this.toggled = false;
    Button.call(this); // superclass constructor
}

// extends
ToggleButton.prototype = Object.create(Button.prototype);
ToggleButton.prototype.constructor = ToggleButton;

let toggleButton = new ToggleButton();
console.log(toggleButton.enabled); // true (from superclass)

```

Using the `class` syntax, however, when one class extends another, `super()` is used to run the superclass’s constructor. This call is required and must be called prior to accessing `this` within the subclass’s constructor. The reason is, `this` - the instance being constructed - is created by the superclass through the call to `super()`. Unlike function constructors, `this` simply doesn’t exist until the superclass constructor is called.

```javascript
class Button {
    constructor () {
        this.enabled = true;
    }
}

class ToggleButton extends Button {
    constructor () {
        // this instance does not yet exist
        // this.toggled = false; // ReferenceError: must call super
        super(); // Calls Button constructor, creates instance
        // this instance now exists
        this.toggled = false; // Ok
    }
}

let toggleButton = new ToggleButton();
console.log(toggleButton.enabled); // true (from superclass)

```

This illustrates a key difference in behavior between function constructors and class constructors: function constructors construct from the bottom up, whereas class constructors construct from the top down.

- `function`: subclass creates, passes instance to superclasses
- `class`: superclass creates, passes instance to subclasses

The effects of this can be more clearly seen when the superclass returns another object explicitly:

```javascript
class Button {
    constructor () {
        return [1, 2, 3];
    }
}

class ToggleButton extends Button {
    constructor () {
        super();
        console.log(this); // [1, 2, 3]
    }
}

let array = new ToggleButton(); // [1, 2, 3]

```

In effect, you can imagine that `this` is a variable that is defined when super is called and then set to its return value.

```javascript
const this = super();

```

The subclass can also return explicitly, and before its call to `super()` which can return before the constructed instance is made. This is not possible with function constructors because the constructed instance is always created immediately when the subclass constructor is invoked.

```javascript
class Button {
    constructor () {
        console.log('never called');
    }
}

class ToggleButton extends Button {
    constructor () {
        return [4, 5, 6];
        super(); // not reached, a ToggleButton never created
    }
}

let array = new ToggleButton(); // [4, 5, 6]

```

If you remember the tip that covered object pooling, the automatic creation of an object that was never used was mentioned as a possible concern. But as long as you’re extending another class, even if its the default `Object`, you can get around that by returning before `super()`.

```javascript
class Noodle extends Object { // <-- must use extends to use super
    constructor () {
        if (Noodle.pool.length) {
            return Noodle.pool.pop(); // use pooled instance
        }
        super(); // <-- now new instance created
        // otherwise implicitly returns new instance
    }
    // ...

```

More info:

- [super on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super)
