Object-Oriented JavaScript — Class Inheritance

John Au-Yeung - Jan 24 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

JavaScript is partly an object-oriented language.

To learn JavaScript, we got to learn the object-oriented parts of JavaScript.

In this article, we’ll look at JavaScript subclasses, mixins, and multiple inheritance.

Subclassing

We can create subclasses from a JavaScript class.

For instance, we can write:

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} speaks`);
  }
}

class Dog extends Animal {
  speak() {
    console.log(`${this.name} woofs`);
  }
}

const mary = new Dog('mary');
Enter fullscreen mode Exit fullscreen mode

to create the Animal class.

The speak method is in the Animal class.

We created a subclass of Animal called Dog which also has the speak method.

If we create a Dog instance, then the speak method in Dog will be used.

So if we write:

mary.speak();
Enter fullscreen mode Exit fullscreen mode

We see:

mary woofs
Enter fullscreen mode Exit fullscreen mode

There are several ways to access the superclass of a class.

We can call super() to call the superclass and pass in the arguments of the parent constructor.

Also, we can call super.<parentClassMethod> to call a parent class’s method.

super.<parentClassProp> lets us access the parent class properties.

So if we have:

class Parent {}

class Child extends Parent {
  constructor(name) {
    this.name = name;
  }
}

const child = new Child('james')
Enter fullscreen mode Exit fullscreen mode

We’ll get the error:

Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
Enter fullscreen mode Exit fullscreen mode

this is because we need to call super first to invoke the parent constructor before we can set the properties of this .

This can be done implicitly if we omit the constructor in Child .

If we have:

class Parent {}

class Child extends Parent {}

const child = new Child()
Enter fullscreen mode Exit fullscreen mode

Then we won’t get an error since a default constructor is provided.

The default is:

constructor(...args) {
  super(...args);
}
Enter fullscreen mode Exit fullscreen mode

Mixins

JavaScript only supports single inheritance, so we can’t use the standard JavaScript syntax to inherit properties from multiple classes.

Instead, we have to compose multiple classes into one with functions.

We can write:

class Person {}

const BackgroundCheck = Tools => class extends Tools {
  check() {}
};

const Onboard = Tools => class extends Tools {
  createEmail() {}
};

class Employee extends BackgroundCheck(Onboard(Person)) {}
Enter fullscreen mode Exit fullscreen mode

We have the BackgroundCheck class that returns a subclass of the Tools class.

So Person is Tools in the Onboard function,.

And Onboard(Person) is Tools in the BackgroundCheck function.

This way, we return a class that has both the check and createEmail methods and we can use the resulting class to create the Employee subclass.

Conclusion

We can create subclasses with the extends keyword.

Also, we can create functions that returns a class and compose them so that we can inherit from multiple classes.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .