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.