DEV Community

Grant
Grant

Posted on

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!

Top comments (3)

Collapse
 
jskodes profile image
Jaime Sandoval

Thanks for this article! I was hoping you could clear something up, though, but no worries if not.

Why do you define chainrings and cogs within the gearing method in the Bicycle class, but in the Fixie class you define them in the constructor? Couldn't you have defined them all within the Bicycle's constructor and passed them as arguments when creating a new Fixie object? I'm kinda new to JavaScript classes, so forgive me if the answer is obvious.

Collapse
 
trentungard profile image
trentungard

Great read! I was having a bit of trouble wrapping my mind around Super and Extends and their use cases, but this brought me up to speed better than anything else I've looked at

Collapse
 
ambicoder profile image
Dimitris

Is there any point at all extending a class without using super?