Inheritance lets a class reuse and extend another class. The new class is the subclass (child), and the one it builds on is the superclass (parent).
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound`;
}
}
class Dog extends Animal {
speak() {
return `${this.name} barks`; // overrides the parent method
}
}
const generic = new Animal("Creature");
const rex = new Dog("Rex");
console.log(generic.speak()); // → Creature makes a sound
console.log(rex.speak()); // → Rex barks
Dog gets everything Animal has (the constructor, the name property) and can override methods with its own version.
super
super gives access to the parent class.
In the constructor, you must call super(...) before using this, so the parent can set itself up.
class Animal {
constructor(name) { this.name = name; }
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // run the parent constructor
this.breed = breed; // then add your own data
}
}
console.log(new Dog("Rex", "Collie")); // → Dog { name: Rex, breed: Collie }
In methods, super.method() calls the parent’s version, which is useful when you want to add to the behaviour instead of replacing it.
class Animal {
speak() { return "makes a sound"; }
}
class Dog extends Animal {
speak() {
return `barks and ${super.speak()}`;
}
}
console.log(new Dog().speak()); // → barks and makes a sound
instanceof
object instanceof Class checks whether the object was created from that class or one of its subclasses.
class Animal {}
class Dog extends Animal {}
const rex = new Dog();
console.log(rex instanceof Dog); // → true
console.log(rex instanceof Animal); // → true (a Dog is an Animal)
console.log(rex instanceof Object); // → true
console.log(new Animal() instanceof Dog); // → false
The “is-a” rule
Use inheritance only when the child is a kind of the parent: a Dog is an Animal, a SavingsAccount is a BankAccount. If you can only say “has a” (“a Car has an Engine”), use composition.
Extending built-in classes
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
console.log(new ValidationError("bad input") instanceof Error); // → true
See Custom Errors.
Things to remember
- Only single inheritance: a class extends one parent.
- Inherited static members come along too.
- Deep inheritance chains are hard to follow. Two or three levels is usually the limit.
- A subclass can access
protected-style things only by convention. JavaScript has public and#privateonly, and#privatefields are not visible to subclasses.
Behind the scenes
extends sets up a link between the prototypes of the two classes. See Prototypes.