Topic 57 of 59 JavaScript Objects, Arrays & Advanced Data Structures Interactive Tutorial

Inheritance in JavaScript: Reusing Properties and Methods Across Objects

23 mins read Last updated: 22 Aug 2026 14453 views
Quick Summary & Key Takeaway Target Skill Level: Beginner to Advanced ES6+

Bottom-Line Answer: JavaScript (JS) is a high-level, single-threaded, just-in-time (JIT) compiled programming language with first-class functions that conforms to the ECMAScript specification. It powers dynamic client-side web interactivity alongside HTML and CSS, and executes backend server runtimes via Node.js, Deno, and Bun.

Target Audience: Frontend developers, full-stack engineers, students & QA testers.
Prerequisites: Basic HTML semantics & fundamental CSS styling rules.
Primary Use Cases: Dynamic web UI, DOM manipulation, asynchronous REST APIs, Node.js backend services.

What is Inheritance in JavaScript? Core Concept & Direct Summary

Core Objective & Problem Statement

How does class inheritance work using extends and super?

Direct Answer Summary
The extends keyword establishes subclass inheritance; super() invokes parent constructor methods.

Imagine building a zoo management system. You need Lions, Penguins, and Elephants. Each has a name, an age, needs to eat and sleep… but lions roar, penguins swim, and elephants spray water. 🦁🐧🐘

Without inheritance, you'd writeeat()andsleep()three times — and every bug fix means editing three files:

script.js
Run Online
// 😩 The copy-paste nightmare:class Lion {  eat() { console.log("eating…"); }  sleep() { console.log("sleeping…"); }  roar() { console.log("ROAR!"); }}class Penguin {  eat() { console.log("eating…"); }      // 😩 duplicated…  sleep() { console.log("sleeping…"); }  // 😩 again…  swim() { console.log("splashing!"); }}

Fixeat()once → every animal heals. That's inheritance:children reuse, extend, and customize what parents define.In this lesson:extendsandsupermastered, method overriding, theprototype chain(the mechanism actually running the show), and the famous "composition over inheritance" wisdom. Let's climb the family tree. 🌳

How Does Inheritance in JavaScript Work? In-Depth Mechanics & Architecture

Subclasses must call super() in their constructor before referencing the 'this' keyword.

The Core Vocabulary 📖

TermMeaningIn the Zoo
Parent / SuperclassThe class being inherited fromAnimal
Child / SubclassThe class doing the inheritingLion
extendsThe keyword creating the linkclass Lion extends Animal
superThe phone line to the parent ☎️super()/super.method()
OverrideChild replaces a parent methodLion's ownspeak()
Prototype chainThe lookup path JavaScript followsLion → Animal → Object

extends: Creating the Parent-Child Link 🔗

script.js
Run Online
class Animal {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  } describe() {
    return `${this.name} is ${this.age} years old 🐾`;
  }
}class Penguin extends Animal {
  swim() {
    return `${this.name} is swimming! 🐧💦`;
  }
}const penny = new Penguin("Penny", 3);
console.log(penny.describe());
// "Penny is 3 years old 🐾" — inherited ✅
console.log(penny.swim());
// "Penny is swimming! 🐧💦" — its own ✅

Whatextendsactually did:it wiredPenguin's prototype chain toAnimal's. When you callpenny.describe():

script.js
Run Online
1. Does penny itself have "describe"? ❌2. Does Penguin.prototype have it? ❌3. Does Animal.prototype have it? ✅ FOUND — run it!

That upward search is theprototype chain— inheritance's true engine (much more below 👇).

super: The Two-Faced Keyword ☎️

superdoes exactly two jobs — both essential:

① super(…) in the Constructor — Calling the Parent's Setup

script.js
Run Online
class ElectricCar extends Vehicle {
  constructor(brand, batteryKwh) {
    super(brand);
    // ☎️ parent's constructor FIRST
    this.batteryKwh = batteryKwh;
    // THEN the child's own setup
  }
}

The unbreakable rules:

script.js
Run Online
class ElectricCar extends Vehicle {
  constructor(brand, batteryKwh) {
    this.brand = brand;
    // ❌ ReferenceError! this doesn't exist yet…
    super(brand);
    // …until super() creates it
  }
}

🚨 Rule 1:In a child constructor,super()must runbefore anythis— the parent builds the foundation before the child decorates.

🚨 Rule 2:A child class that defines a constructormustcallsuper()— skip it, and anythisuse throws.

💡 Exception:if the child hasno constructor at all, JavaScript auto-generates one that just passes everything through:constructor(...args) { super(...args); }— that's why constructor-less children work.

② super.method() — Calling the Parent's Version

script.js
Run Online
class Animal {
  speak() {
    return "…some sound…";
  }
}class Dog extends Animal {
  speak() {
    const base = super.speak();
    // ☎️ borrow the parent's version
    return `${base} Woof! 🐕`;
    // …and extend it
  }
}console.log(new Dog().speak());
// "…some sound… Woof! 🐕" ✅

Child gets the final word, but can still consult the parent —extensioninstead of full replacement.


Method Overriding: The Child's Veto 🎭

When a child defines a method with thesame nameas the parent's, the child's wins — this is polymorphism (Lesson 23's Pillar #3) in action:

script.js
Run Online
class Animal {
  speak() {
    return "…generic sound…";
  }
}class Dog extends Animal {
  speak() {
    return "Woof! 🐕";
  } // overrides Animal's
}class Cat extends Animal {
  speak() {
    return "Meow! 🐈";
  } // overrides Animal's
}class Cow extends Animal {
  // no override — keeps the parent's
}const choir =[new Dog(), new Cat(), new Cow()];
choir.forEach(a => console.log(a.speak()));
// Woof! 🐕
// Meow! 🐈
// …generic sound…        ← parent's version survived here

Why the child wins:the prototype chain searchesnearest first.dog.speakis found onDog.prototypebefore the search ever reachesAnimal.prototype.

Overriding works for data properties too:

script.js
Run Online
class Vehicle {
  wheels = 4;
}class Motorcycle extends Vehicle {
  wheels = 2;
  // 🏍️ overridden field
}console.log(new Motorcycle().wheels);
// 2 ✅

The Prototype Chain: Inheritance's True Engine ⚙️

Here's whatextendsactually builds— and why Lesson 48's constructor knowledge pays off:

script.js
Run Online
const leo = new Lion("Leo", 5);

The chain JavaScript searches forleo.eat():

script.js
Run Online
leo(the instance)↓__proto__ linkLion.prototype ← roar() lives here↓__proto__ linkAnimal.prototype ← eat(), sleep() live here ✅ found!↓__proto__ linkObject.prototype ← toString(), hasOwnProperty() live here↓__proto__ linknull ← the end of the road 🛑

The search rule:look on the object → its prototype → that prototype's prototype → …until found ornull. First match wins (that's overriding!). Exhaust the chain →undefined(or TypeError if you tried to call it).

You CanSeethe Chain 👀

script.js
Run Online
console.log(Object.getPrototypeOf(leo) === Lion.prototype);
// true
console.log(Object.getPrototypeOf(Lion.prototype) === Animal.prototype);
// true ✅
console.log(leo instanceof Lion);
// true
console.log(leo instanceof Animal);
// true — the chain proves family! 🧬
console.log(leo instanceof Object);
// true — everyone descends from Object

instanceof(Lesson 48) literally walks this chain asking "are you in here?"

🔑 The big reveal:classes andextendsare beautiful syntax — but the engine underneath is this prototype chain, the same one constructor functions used in 1995. JavaScript inheritance isprototype delegation, not classical copying. Children don'treceive copiesof parent methods — theydelegate upwardto shared ones.

🌍 This Explains Everything Built-In

script.js
Run Online
const arr =[1, 2, 3];
arr.map(x => x);
// ← found on Array.prototype
arr.hasOwnProperty("x");
// ← found on Object.prototype — arrays inherit it!

Every array inherits fromArray.prototype, which inherits fromObject.prototype. That's why[].toString()works even though you never wrote it. The chain has been serving you since Lesson 1. 😄


Multi-Level Inheritance: The Family Tree 🌲

Chains can run several generations deep:

script.js
Run Online
class Animal {
  breathe() {
    return "breathing… 💨";
  }
}class Mammal extends Animal {
  feedYoung() {
    return "nursing 🍼";
  }
}class Dog extends Mammal {
  fetch() {
    return "fetching! 🎾";
  }
}const rex = new Dog();
console.log(rex.fetch());
// Dog's own
console.log(rex.feedYoung());
// from Mammal (grandparent) ✅
console.log(rex.breathe());
// from Animal (great-grandparent) ✅

rexsearches Dog → Mammal → Animal → Object — the whole ancestry in one lookup.

⚠️ The Deep-Hierarchy Warning

Three levels is fine. Six levels is a maintenance horror:

script.js
Run Online
Animal → Mammal → Canine → PetDog → RescueDog → CertifiedRescueDog 😵

Deep trees are fragile — changeAnimaland seven generations wobble. Which brings us to the famous alternative…


🥊 Composition vs Inheritance: The Professional Debate

"Favor composition over inheritance."— the design principle behind a thousand interviews 🎤

The problem inheritance can't solve cleanly:what if a Penguin canswimand a Parrot canfly— but an Ostrich does neither, and a Duck doesboth? A single inheritance chain forces impossible choices.

Composition's answer:build objects fromcapability piecesinstead of family trees:

script.js
Run Online
// 🧩 Capabilities as reusable pieces:
const canSwim = {
  swim() {
    return `${this.name} swims! 🏊`;
  }
};
const canFly = {
  fly() {
    return `${this.name} flies! 🦅`;
  }
};
class Bird {
  constructor(name) {
    this.name = name;
  }
}class Penguin extends Bird {
}Object.assign(Penguin.prototype, canSwim);
// 🧩 give penguins swimming
class Duck extends Bird {
}Object.assign(Duck.prototype, canSwim, canFly);
// 🧩 ducks get BOTH!
console.log(new Penguin("Penny").swim());
// "Penny swims! 🏊" ✅
console.log(new Duck("Donald").fly());
// "Donald flies! 🦅" ✅

Mix and match capabilities without bending the family tree.

Inheritance 🌳Composition 🧩
Relationship"is a" (Dogis anAnimal)"has a / can do" (Duckcanfly)
Reuse styleVertical — down the treeHorizontal — snap pieces together
FlexibilityRigid hierarchiesMix & match freely
Deep chainsFragile 😬Avoided entirely
Best whenClear, stable IS-A (3 levels max)Shared capabilities across unrelated types

Beginner verdict:learn inheritance first (it's everywhere — frameworks, DOM, built-ins). Reach for composition when hierarchies start forcing weird parents. Most real codebases use both. 🤝

🛠️ Mini Project: The Zoo System 🦁

Everything from this lesson in one working hierarchy:

script.js
Run Online
// 🦁 Zoo Management — inheritance, super, overriding, composition
class Animal {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  } describe() {
    return `${this.name} (${this.constructor.name}, age ${this.age})`;
  } speak() {
    return "…";
  }
}// 🧩 Composed capability:
const canPerformTricks = {
  doTrick() {
    return `${this.name} does a backflip! 🤸`;
  }
};
class Lion extends Animal {
  speak() {
    // 🎭 override
    return "ROAAAR! 🦁";
  }
}class Penguin extends Animal {
  speak() {
    return `${super.speak()} …squawk! 🐧`;
    // ☎️ extend the parent's
  } swim() {
    return `${this.name} dives in! 💦`;
    // child's own
  }
}class Parrot extends Animal {
}Object.assign(Parrot.prototype, canPerformTricks);
// 🧩 composed skill
const animals =[ new Lion("Leo", 5), new Penguin("Penny", 3), new Parrot("Rio", 2)];
// 🎪 Polymorphism parade — one loop, every behavior:
animals.forEach(a => console.log(`${a.describe()} says: ${a.speak()}`));
console.log(new Penguin("Penny", 3).swim());
// Penguin-only skill
console.log(new Parrot("Rio", 2).doTrick());
// composed skill ✅
console.log(new Lion("Leo", 5) instanceof Animal);
// true

Output:

script.js
Run Online
Leo(Lion, age 5) says: ROAAAR! 🦁Penny(Penguin, age 3) says: … …squawk! 🐧Rio(Parrot, age 2) says: …Penny dives in! 💦Rio does a backflip! 🤸true

Inheritance for the family structure,superfor parent collaboration, overriding for personality, composition for bonus skills — the complete professional toolkit in one zoo. 🏆

Output:

script.js
Run Online
Leo(Lion, age 5) says: ROAAAR! 🦁Penny(Penguin, age 3) says: … …squawk! 🐧Rio(Parrot, age 2) says: …Penny dives in! 💦Rio does a backflip! 🤸true

Inheritance for the family structure,superfor parent collaboration, overriding for personality, composition for bonus skills — the complete professional toolkit in one zoo. 🏆


Common Beginner Mistakes (And Fixes)

❌ Mistake🔍 What Happens✅ Fix
thisbeforesuper()ReferenceErrorsuper() is the constructor's first act
Forgettingsuper()entirely in a child constructorReferenceError on anythisChild constructor? super() required
Expecting child methods in the parentParent can't see downward — one-way streetInheritance flows down only
6-level class hierarchiesFragile, untestable code 😵2–3 levels; compose beyond that
Overriding and losing parent behaviorBase logic silently gonesuper.method()to extend instead
Thinking children copy parent methodsMisunderstanding memory/lookupChildrendelegatevia the prototype chain
class Dog extends animal {}(instance, not class)TypeErrorextends needs aclass, not an object

Quick Self-Check: Lesson 56 Quiz 🧠

  1. What two keywords implement class inheritance, and what does each do?
  2. What's the output?
    script.js
    Run Online
    class A {
      greet() {
        return "A";
      }
    }class B extends A {
      greet() {
        return super.greet() + "B";
      }
    }console.log(new B().greet());
  3. Why mustsuper()come beforethisin a child constructor?
  4. In the chainleo (Lion extends Animal), where does JavaScript look for a method, in what order?
  5. When does composition beat inheritance?

(Answers: 1. extends links a child class to a parent; super calls the parent's constructor (super()) or methods (super.method()) · 2. "AB" — the child's greet runs, borrowing the parent's via super · 3. The parent's constructor creates/initializes the instance — before super() runs,thisdoesn't exist yet, so touching it throws a ReferenceError · 4. leo itself → Lion.prototype → Animal.prototype → Object.prototype → null (first match wins) · 5. When unrelated types need shared capabilities (fly/swim across different families), or hierarchies grow beyond ~3 levels — mix in capabilities instead of forcing a family tree)

JavaScript Decision Matrix & Syntax Comparison

Understanding the mechanical differences between variable declarations and execution environments is critical for writing performant, bug-free modern JavaScript.

Variable Declarations: var vs let vs const
Feature / Propertyvar (Legacy ES5)let (Modern ES6+)const (Modern ES6+)
ScopeFunction ScopeBlock Scope ({})Block Scope ({})
Hoisting BehaviorHoisted (initialized as undefined)Hoisted (Temporal Dead Zone - ReferenceError)Hoisted (Temporal Dead Zone - ReferenceError)
Reassignable✓ Yes✓ Yes✗ No (Immutable binding)
Redeclarable in Same Scope✓ Yes (Error-prone)✗ No (SyntaxError)✗ No (SyntaxError)
Window Object BindingCreates property on windowDoes not attach to windowDoes not attach to window
Environment Decision Matrix: Browser Client-Side vs Node.js Server-Side
DimensionClient-Side (Web Browser)Server-Side (Node.js / Deno)
Global Objectwindow, document, navigatorglobal, process, globalThis
DOM & UI Manipulation✓ Full access (document.querySelector)✗ No DOM (Headless / Non-UI)
File System & OS Access✗ Blocked (Sandboxed security)✓ Full access (fs, os, child_process)
Primary FocusInteractive UI, animations, client stateREST APIs, microservices, databases, I/O streaming

Runnable JavaScript Code Example & Practical Implementation

script.js
Run Online
class Animal {
  constructor(name) {
    this.name = name;
  } speak() {
    return `${this.name} makes a noise.`;
  }
}class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  } speak() {
    return `${this.name} barks!`;
  }
}const d = new Dog('Rex', 'German Shepherd');
console.log(d.speak());
// 'Rex barks!'

Frequently Asked Questions & Technical Interview Insights

Technical Interview & Viva Questions

Frequently asked questions for frontend & full-stack roles
Q

Q: What happens if a derived class constructor omits super()?

A: Referencing 'this' or exiting the derived constructor without calling super() throws a ReferenceError.

Related Tools, Tutorials & Authoritative References

Recommended Interactive Tools

Authoritative Standards & Citations