Javascript ES6: "Super" and "Extends"

gduple

Grant

Posted on July 6, 2020

Javascript ES6: "Super" and "Extends"

Keywords super and extends are integral parts of Javascript's ES6 subclass syntax, but super's role can seem mysterious. To get a better understanding of how they work, let's start with an example of inheritance in pseudoclassical ES6 pattern:

class Bicycle {
  constructor(brand, color) {
    this.brand = brand;
    this.color = color;
  }

  describe() {
    return (`This bicycle is a ${this.color} ${this.brand}.`);
  }

  gearing(chainRings, cogs) {
    this.chainRings = chainRings;
    this.cogs = cogs;
    this.speeds = this.cogs * this.chainRings;
    if (this.speeds > 1) {
      return (`This ${this.brand} is a ${this.speeds}-speed.`);
    }
    if (this.speeds === 1) {
      return (`This ${this.brand} is a single-speed.`);
    }
  }
}

const pug = new Bicycle("Peugeot", "red");
console.log(pug.describe()); /* This bicycle is a 
red Peugeot. */
Enter fullscreen mode Exit fullscreen mode

In the example above, the Bicycle class has a constructor function to create a Bicycle, and a method, gearing, to report its gearing. Note the class keyword, and capitalization of the class name, Bicycle, both of which are important components of this instantiation pattern. A new instance of a Bicycle is created with the keyword new.

Now, on to the subclass business. Let's create a subclass Fixie that takes on Bicycle's properties.

class Fixie extends Bicycle {
    constructor(brand, color) {
      this.chainRings = 1;
      this.cogs = 1;
      this.isFixedGear = true;
    }

    gearing() {
      if (this.isFixedGear === true) {
        return (`This ${this.brand} is a fixed-gear.`);
      }
    }
}
Enter fullscreen mode Exit fullscreen mode

It's easy to see that extends directs subclass Fixie to take on class Bicycle's properties (much like the underscore library's extend method extends an object(s) properties into another). Fixie, however, has its own constructor that adds properties, and it overrides one of its inherited methods, gearing.

What's less apparent here is that this code won't work as written. Attempting to create a new instance of Fixie will throw a ReferenceError Specifically, mine says Must call super constructor in derived class before accessing 'this' or returning from derived constructor—if only all errors were this helpful! We'll need to user super somehow to get things up and running—but how? And why?

According to javascript.info, "In JavaScript, there’s a distinction between a constructor function of an inheriting class (so-called “derived constructor”) and other functions." The problem is a derived constructor called with keyword new does not create an empty object assigned to this, because it "expects the parent constructor to do this job." So all we have to do is call the constructor in super (the parent class)—fair enough. Here's another go at it:


class Fixie extends Bicycle {
    constructor(brand, color) {
      super(brand, color);
      this.chainRings = 1;
      this.cogs = 1;
      this.isFixedGear = true;
    }

    gearing() {
      if (this.isFixedGear === true) {
        return (`This ${this.brand} is a fixed-gear.`);
      }
    }
}


const moto = new Fixie("Motobecane", "blue");
console.log(moto.gearing()); /* This Motobecane is a
fixed-gear. */
Enter fullscreen mode Exit fullscreen mode

The important thing to note is that super must be called before any use of keyword this, or there will be no this to refer to, and an error will be thrown. Now let's look at one more use of super:

class Fixie extends Bicycle {
    constructor(brand, color) {
      super(brand, color);
      this.chainRings = 1;
      this.cogs = 1;
      this.isFixedGear = true;
    }

    gearing() {
      if (this.isFixedGear === true) {
        return (`This ${this.brand} is a fixed-gear.`);
      }
    }

    describe() {
      return `${super.describe()} This bike is a fixie.`
    }
}

console.log(moto.describe()) /* This bicycle is a blue
Motobecane. This bike is a fixie. */
Enter fullscreen mode Exit fullscreen mode

Now we've used a call of the super's describe method while actually overriding describe within the subclass. The new method will return the value of describe's message from the Bicycle class along with more information describing the bike as a fixie.

Keyword super doesn't have to be mysterious! Just remember that it refers to the parent class (thinking "superclass" may help), and that it must be called in the subclass's constructor function to start up a new empty object for keyword this.
Super!

💖 💪 🙅 🚩
gduple
Grant

Posted on July 6, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related