Inheritance in JavaScript
Introduction
Inheritance lets a child class reuse and extend a parent class. JavaScript uses prototype chains; extends and super express parent/child relationships clearly. This chapter covers method overriding, calling parent constructors, and when composition is a better fit than deep inheritance trees.
Prerequisites
extends Base Class
// Animal base, Dog child
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound`;
}
}
class Dog extends Animal {
speak() {
return `${this.name} says woof`;
}
}
const rex = new Dog("Rex");
console.log(rex.speak());super in Constructor
Child must call super() before using this:
// Pass args to parent constructor
class Employee extends Person {
constructor(name, department) {
super(name);
this.department = department;
}
}
class Person {
constructor(name) {
this.name = name;
}
}
const emp = new Employee("Ada", "Engineering");
console.log(emp.name, emp.department);Warning
Forgetting super() in a subclass constructor throws ReferenceError when you touch this.
super to Call Parent Methods
// Extend behavior, not replace entirely
class Admin extends User {
constructor(name) {
super(name, "admin");
}
describe() {
return `${super.describe()} [elevated]`;
}
}
class User {
constructor(name, role) {
this.name = name;
this.role = role;
}
describe() {
return `${this.name} (${this.role})`;
}
}
console.log(new Admin("Lin").describe());instanceof Along the Chain
const d = new Dog("Max");
console.log(d instanceof Dog);
console.log(d instanceof Animal);
console.log(d instanceof Object);Overriding vs Overloading
JavaScript has no method overloading by signature—last definition wins. Use default parameters or different method names instead.
Prefer Composition When Possible
// Has-a instead of deep is-a chains
class Engine {
start() {
return "engine on";
}
}
class Car {
constructor() {
this.engine = new Engine();
}
start() {
return this.engine.start();
}
}
console.log(new Car().start());Many designs use small classes plus plain functions instead of five levels of extends.
Mini Example: Shape Hierarchy
class Shape {
constructor(color) {
this.color = color;
}
}
class Circle extends Shape {
constructor(color, radius) {
super(color);
this.radius = radius;
}
area() {
return Math.PI * this.radius ** 2;
}
}
const c = new Circle("red", 3);
console.log(c.color, c.area().toFixed(2));FAQ
Can I extend built-ins like Array?
Possible but tricky—prefer composition or utility functions for extending array behavior.
Multiple inheritance?
Not directly—one extends parent; mixins or interfaces (TypeScript) address some cases.
Object.create vs extends?
extends is standard for class-based hierarchies; Object.create for one-off delegation.
What comes next?
Map and Set—built-in collections in the standard library.