JavaScript Inheritance
Table of Contents + −
In the previous lesson, we learned how a constructor sets up each object when a class is created. Now let’s see how one class can build on another using inheritance.
🧬 What is Inheritance?
Inheritance lets one class build on another. The class that gives away its features is the parent class, and the class that receives them is the child class. The child inherits the parent’s properties and methods, so you do not have to write them again.
You set up inheritance with the extends keyword. The child class lists the parent it extends, and from that point it owns everything the parent has.
class Animal { constructor(name) { this.name = name; }
eat() { console.log(`${this.name} is eating.`); }}
class Dog extends Animal {}
const rex = new Dog("Rex");rex.eat(); // Rex is eating.Let’s walk through what each line does:
class Animaldefines the parent class with anameproperty and aneat()method.class Dog extends Animal {}makesDoga child ofAnimal. Theextendskeyword is what links the two, soDogautomatically owns everythingAnimalhas, even with an empty body.const rex = new Dog("Rex")creates aDogobject. SinceDoghas no constructor, JavaScript usesAnimal’s constructor and setsthis.nameto"Rex".rex.eat()calls a methodDognever defined. JavaScript looks up to the parent, findseat()onAnimal, and runs it. That is inheritance: the child gets the parent’s abilities for free.
🏗️ Calling the Parent with super()
When the child class needs its own constructor, it must call the parent constructor first. The super() function runs the parent’s constructor so the inherited properties are set up correctly.
class Animal { constructor(name) { this.name = name; }
eat() { console.log(`${this.name} is eating.`); }}
class Dog extends Animal { constructor(name, breed) { super(name); // runs Animal's constructor and sets this.name this.breed = breed; // Dog's own property }}
const rex = new Dog("Rex", "Labrador");console.log(rex.name); // Rexconsole.log(rex.breed); // LabradorLet’s trace the constructor step by step:
constructor(name, breed)givesDogits own constructor that accepts two values.super(name)callsAnimal’s constructor and passesnameup to it.Animalthen runsthis.name = name, so the inherited property is set.this.breed = breedadds a property that belongs only toDog. We can only write this aftersuper()has finished building the object.new Dog("Rex", "Labrador")runs both steps, sorex.namereads"Rex"from the parent andrex.breedreads"Labrador"from the child.
The child reuses the parent’s setup with super() and then extends it with its own property.
super() must come first
Inside a child constructor, super() has to run before you touch this.
JavaScript will not let you use this until the parent constructor has
finished building the object.
🐕 Adding and Overriding Methods
A child class is not limited to what it inherits. It can add brand new methods, and it can override a parent method by defining one with the same name.
class Animal { constructor(name) { this.name = name; }
speak() { console.log(`${this.name} makes a sound.`); }}
class Dog extends Animal { constructor(name, breed) { super(name); this.breed = breed; }
// New method that Animal does not have fetch() { console.log(`${this.name} fetches the ball.`); }
// Override: replaces Animal's speak() speak() { console.log(`${this.name} barks.`); }}
const rex = new Dog("Rex", "Labrador");rex.fetch(); // Rex fetches the ball.rex.speak(); // Rex barks.Let’s see how the child changes the parent’s behavior:
super(name)still runs first to set up the inheritednameproperty, thenthis.breed = breedadds the child’s own property.fetch()is a brand new method thatAnimaldoes not have, so it belongs only toDog.speak()has the same name as the method inAnimal. Defining it again overrides the parent version, so the child’sspeak()wins.rex.fetch()runs the new method, andrex.speak()runs the overridden one, printingRex barks.instead of the parent’s message.
Overriding means the more specific class replaces the general behavior with its own.
♻️ Why Inheritance Reduces Duplication
Without inheritance, every class repeats the same shared code. Picture a Dog, a Cat, and a Bird that all need a name and an eat() method. Writing that code three times means three places to fix when something changes.
With inheritance you write the shared parts once in Animal, then let each child extend it.
class Animal { constructor(name) { this.name = name; }
eat() { console.log(`${this.name} is eating.`); }}
class Cat extends Animal { speak() { console.log(`${this.name} meows.`); }}
class Bird extends Animal { speak() { console.log(`${this.name} chirps.`); }}Let’s see how the shared code stays in one place:
class Animalholds thenameproperty and theeat()method that every animal needs, written only once.class Cat extends AnimalreusesAnimal’snameandeat(), then adds its ownspeak()that meows.class Bird extends Animaldoes the same, but itsspeak()chirps instead.- Neither child rewrites
nameoreat(). Each one only writes the part that makes it different.
Less repeated code means fewer bugs and one clear place to make changes.
⚠️ Common Mistakes to Avoid
| Mistake | Problem | Solution |
Forgetting super() in the child constructor | JavaScript throws a ReferenceError when you use this | Call super(...) as the first line of the constructor |
Using this before super() | The object is not built yet, so this is unavailable | Always run super() before any this.something = ... |
| Overriding a method by accident | A child method with the same name silently replaces the parent’s | Use a different name, or call super.method() to keep the parent behavior |
Reuse the parent inside an override
Inside an overriding method you can still reach the parent version with
super.speak(). That lets you run the parent’s behavior and then add to it,
instead of replacing it completely.
🔧 Try It Yourself!
- Create a parent class
Animalwith anameproperty and aneat()method. - Create a child class
Dogthat extendsAnimaland callssuper(name)in its constructor. - Add a new
breedproperty toDogafter thesuper()call. - Add a
fetch()method toDogand override the parent’sspeak()method. - Create a
Dogobject and call the inherited, the new, and the overridden methods to see each one work.
🧩 What You’ve Learned
- ✅ Inheritance lets a child class build on a parent class with
extends - ✅ The child inherits the parent’s properties and methods
- ✅
super()calls the parent constructor and must run beforethis - ✅ A child can add new methods and override parent methods
- ✅ Inheritance keeps shared code in one place and reduces duplication
🚀 What’s Next?
Now that classes can share behavior, we will learn how to protect the data inside them. Let’s continue to Encapsulation.