Skip to content

Class Inheritance

This lesson explains Class Inheritance with clear examples, use cases, and best practices so you can use modern JavaScript confidently in real projects.

ES6+ Class Inheritance Overview

Class inheritance lets one class extend another and reuse its properties and methods. In ES6, you use extends to create a child class and super to call the parent constructor or inherited methods.

Inheritance is useful when one class is a specialized version of another, such as Admin extending User or Dog extending Animal.

Feature Description
Introduced In ES6 (ECMAScript 2015)
Keyword extends
Parent Access super() and super.method()
Child Class Inherits methods and prototype chain
Override Child can redefine parent methods
Common Uses Models, UI components, domain entities

Basic Class Inheritance Example

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

  speak() {
    return `${this.name} makes a sound`;
  }
}

class Dog extends Animal {
  speak() {
    return `${this.name} barks`;
  }
}

const dog =
  new Dog("Buddy");

console.log(dog.speak());
console.log(dog.name);

Dog inherits from Animal and overrides the speak() method with its own behavior.

How Class Inheritance Works

When a class extends another, the child class gets access to the parent prototype chain. The child can reuse parent methods and add or override its own behavior.

Step Description Example
Create Parent Define the base class. class User
Extend Parent Create a child with extends. class Admin extends User
Call super() Initialize parent state in constructor. super(name)
Add Behavior Define child-only methods. grantAccess()
Override Methods Replace inherited methods if needed. speak()

Using super in the Constructor

class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }
}

class Admin extends User {
  constructor(name, email, role) {
    super(name, email);
    this.role = role;
  }

  describe() {
    return `${this.name} is an ${this.role}`;
  }
}

const admin =
  new Admin(
    "Alex",
    "alex@example.com",
    "super-admin"
  );

console.log(admin.describe());

In a child class constructor, you must call super() before using this.

Calling Parent Methods with super

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

  getDetails() {
    return `Employee: ${this.name}`;
  }
}

class Manager extends Employee {
  constructor(name, team) {
    super(name);
    this.team = team;
  }

  getDetails() {
    return `${super.getDetails()}, Team: ${this.team}`;
  }
}

const manager =
  new Manager("Sam", "Frontend");

console.log(
  manager.getDetails()
);

Use super.methodName() when a child method needs to extend rather than completely replace parent behavior.

Method Overriding

class Shape {
  area() {
    return 0;
  }
}

class Rectangle extends Shape {
  constructor(width, height) {
    super();
    this.width = width;
    this.height = height;
  }

  area() {
    return this.width * this.height;
  }
}

const rect =
  new Rectangle(8, 5);

console.log(rect.area());

Child classes can override inherited methods to provide specialized implementations while keeping a shared parent interface.

Multi-Level Inheritance

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

class Employee extends Person {
  constructor(name, id) {
    super(name);
    this.id = id;
  }
}

class Manager extends Employee {
  constructor(name, id, department) {
    super(name, id);
    this.department = department;
  }

  profile() {
    return `${this.name} manages ${this.department}`;
  }
}

const manager =
  new Manager("Riya", 12, "Support");

console.log(manager.profile());

Inheritance can span multiple levels, but deep chains should be used carefully to avoid hard-to-maintain class hierarchies.

instanceof with Inheritance

class Vehicle {
  move() {
    return "Moving";
  }
}

class Car extends Vehicle {
  drive() {
    return "Driving";
  }
}

const car = new Car();

console.log(
  car instanceof Car
);
console.log(
  car instanceof Vehicle
);

A child class instance is also an instance of its parent class in the prototype chain.

ES5 vs ES6 Inheritance

// ES6
class Parent {
  greet() {
    return "Hello";
  }
}

class Child extends Parent {
  greet() {
    return super.greet() + " Child";
  }
}

// ES5 style
function ParentFn() {}

ParentFn.prototype.greet =
  function () {
    return "Hello";
  };

function ChildFn() {}
ChildFn.prototype =
  Object.create(
    ParentFn.prototype
  );

ES6 class inheritance is cleaner syntax built on JavaScript's prototype system.

Inheritance vs Composition

Approach Best For Risk
Inheritance True is-a relationships Deep class hierarchies
Composition Combining behaviors More boilerplate sometimes
Override Specialized child behavior Unexpected parent changes
Modern Preference Favor shallow inheritance Easier maintenance

Common Class Inheritance Use Cases

  • Creating specialized user roles from a base user class.
  • Extending base UI components with custom behavior.
  • Building domain models such as shapes, accounts, or products.
  • Sharing common service logic across related classes.
  • Overriding methods for platform-specific implementations.
  • Reusing validation and initialization from parent classes.
  • Designing class-based APIs in libraries and frameworks.

Class Inheritance Best Practices

  • Use inheritance for clear is-a relationships.
  • Always call super() in child constructors first.
  • Override methods intentionally, not accidentally.
  • Prefer shallow inheritance over deep hierarchies.
  • Consider composition when behavior can be mixed in instead.
  • Keep parent classes focused and reusable.
  • Document which methods are meant to be overridden.

Common Inheritance Mistakes

  • Using this before calling super().
  • Forgetting to call super() in a child constructor.
  • Creating overly deep inheritance chains.
  • Using inheritance when composition would be simpler.
  • Overriding methods without understanding parent behavior.
  • Assuming private fields are inherited by child classes.
  • Extending classes only to reuse one small helper method.

Key Takeaways

  • Use extends to create a child class from a parent class.
  • Use super() in constructors and super.method() for parent methods.
  • Child classes can inherit, extend, and override parent behavior.
  • Inheritance works through JavaScript's prototype chain.
  • Prefer clear, shallow inheritance for maintainable object-oriented code.

Pro Tip

If a child class only needs part of a parent's behavior, override the method and call super.methodName() instead of copying parent code.