Inheritance in JavaScript: Extending Your Classes!
Table of contents
- What is Inheritance?
- Inheritance in JavaScript – Using Prototypes
- Let’s Build a Family – Implementing Inheritance
- Family Tree Flowchart – How Inheritance Works
- Challenge – Build a Family Tree Using Inheritance
- Passing Down Traits with Inheritance
- Prototypal Inheritance – How JavaScript Does It Behind the Scenes
- The Prototype Chain in Action
- Overriding Methods – Customizing Child Class Behavior
- Challenge – Extending the Family Tree with Advanced Inheritance
- Conclusion – Extending Functionality Through Inheritance
- Let’s tackle Polymorphism next!
Imagine your family tree. You inherit traits from your parents, like your last name or eye color, and you may pass those traits down to your children. In JavaScript, inheritance works the same way: a parent class passes down properties and methods to its child classes.
Think of classes in JavaScript as family members. The parent class has certain traits (properties and methods), and the child class inherits those traits. But just like in real life, each child can also have their own unique characteristics.
What is Inheritance?
In programming, inheritance allows one class (the child) to borrow traits from another class (the parent). This helps you reuse code without needing to write the same thing over and over again. Just like you may have inherited your family’s last name, child classes can inherit methods like getFullName()
from their parent class.
Inheritance in JavaScript – Using Prototypes
In JavaScript, inheritance is handled by something called prototypal inheritance. Each class has a prototype—an object that stores shared traits (methods and properties) that can be passed down to child classes. If a child class doesn’t have a certain method, JavaScript looks up the family tree, checking the prototype of the parent class.
Let’s break this down with our family tree theme:
The parent class holds the shared traits (like
lastName
orgetFullName()
).The child class inherits these traits, but can also have its own traits (like
favoriteToy
).
Let’s Build a Family – Implementing Inheritance
Now, let’s create a family in JavaScript. We’ll start with a Person
class (the parent) and then create a Child
class that inherits from Person
. The child will have all the traits of the parent, plus a few of their own.
Code Snippet: Building a Family with Inheritance
// Parent class (Person)
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
// Parent method
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
}
// Child class inherits from Person
class Child extends Person {
constructor(firstName, lastName, favoriteToy) {
super(firstName, lastName); // Inherit parent's properties
this.favoriteToy = favoriteToy; // Child's unique trait
}
// Child's unique method
play() {
console.log(`${this.getFullName()} is playing with ${this.favoriteToy}.`);
}
}
// Create an instance of the Child class
const john = new Child("John", "Doe", "Lego");
john.play(); // Output: John Doe is playing with Lego.
Explanation:
Parent Class (
Person
): This class holds shared traits likefirstName
andlastName
, along with the methodgetFullName()
which returns the full name.Child Class (
Child
): The child inherits these traits using theextends
keyword and gets access to thegetFullName()
method. It also adds a new propertyfavoriteToy
and a methodplay()
to showcase its unique behavior.
Think of Person
as the parent who passes down the family name (lastName
) to their child. The child class, Child
, can also have its own traits like a favorite toy. The play()
method lets the child show off this unique trait.
Family Tree Flowchart – How Inheritance Works
Here’s a simple family tree to show how inheritance works in JavaScript. Just like how family members share common traits, child classes in JavaScript inherit methods and properties from their parent class.
Person (Parent Class)
| (Traits: firstName, lastName, getFullName())
-----------------
| |
Child AnotherClass
(Inherits from Person) (Inherits from Person)
(Adds favoriteToy and play())
In this flowchart:
The Person class acts as the parent, holding shared traits.
The Child class inherits these shared traits but adds its own traits, just like how children may inherit their parent’s last name but have their own hobbies or interests.
Challenge – Build a Family Tree Using Inheritance
Now it’s your turn! Let’s create a full family tree using inheritance in JavaScript. The challenge is to build out family members who share some traits but also have their own unique characteristics.
Challenge Instructions:
Create a
Person
class: This will act as the base parent class. It should havefirstName
,lastName
, and a method to display the full name (getFullName()
).Create a
Parent
andChild
class: Both should inherit fromPerson
, but add their own properties and methods. For example, aParent
might have ajob
, and aChild
might have afavoriteGame
.Extend the family tree: Try adding more classes for other family members, like
Grandparent
orSibling
.
Example:
// Parent class
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
}
// Parent class inheriting from Person
class Parent extends Person {
constructor(firstName, lastName, job) {
super(firstName, lastName);
this.job = job;
}
work() {
console.log(`${this.getFullName()} is working as a ${this.job}.`);
}
}
// Child class inheriting from Person
class Child extends Person {
constructor(firstName, lastName, favoriteGame) {
super(firstName, lastName);
this.favoriteGame = favoriteGame;
}
play() {
console.log(`${this.getFullName()} is playing ${this.favoriteGame}.`);
}
}
// Creating instances
const mom = new Parent("Jane", "Doe", "Doctor");
const son = new Child("Jack", "Doe", "Hide and Seek");
mom.work(); // Output: Jane Doe is working as a Doctor.
son.play(); // Output: Jack Doe is playing Hide and Seek.
Passing Down Traits with Inheritance
In this first part, we’ve introduced inheritance using the family tree analogy, showing how classes in JavaScript can pass down traits (properties and methods) to their child classes. This allows us to create reusable code while giving each class its own unique behaviors. Inheritance makes your code more flexible and organized, just like how family traits are passed down through generations.
In the next part, we’ll dive deeper into the technical details of prototypal inheritance and explore how JavaScript handles inheritance behind the scenes.
Prototypal Inheritance – How JavaScript Does It Behind the Scenes
Previously, we looked at how classes and inheritance work, but there’s more happening behind the scenes. Prototypal inheritance is at the core of how JavaScript handles inheritance. Every object in JavaScript has an internal link to another object called its prototype.
Let’s dive into what that really means:
When you create an object or class, JavaScript automatically links it to a prototype object.
If you try to access a method or property that doesn’t exist on the object itself, JavaScript will look up the prototype chain to find it.
This prototype chain is what allows child classes to inherit methods and properties from their parent classes.
The Prototype Chain in Action
Let’s break down how the prototype chain works with an example. When you create a new object from a class, JavaScript connects that object to the class’s prototype. If the object doesn’t have a method or property, JavaScript checks the prototype, then the prototype’s prototype, and so on, until it finds what it’s looking for or reaches the end of the chain.
Code Snippet: Understanding the Prototype Chain
// Parent class
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
}
// Child class
class Child extends Person {
constructor(firstName, lastName, favoriteToy) {
super(firstName, lastName);
this.favoriteToy = favoriteToy;
}
play() {
console.log(`${this.getFullName()} is playing with ${this.favoriteToy}.`);
}
}
const john = new Child("John", "Doe", "Lego");
// Let's explore the prototype chain
console.log(john); // Shows the Child instance, which has a link to Person's prototype
console.log(john.__proto__); // Links to the Child prototype
console.log(john.__proto__.__proto__); // Links to Person's prototype
Explanation:
__proto__
: This property (though not often used in code) shows the internal link to the object’s prototype.The prototype chain starts with the
john
object (an instance ofChild
), which links to theChild
prototype and then links to thePerson
prototype. If a method isn’t found onjohn
, JavaScript looks up the chain to find it.
Overriding Methods – Customizing Child Class Behavior
Just like children can sometimes have different opinions from their parents, child classes can override methods from their parent class. This allows you to customize the behavior of a child class while still inheriting the general structure from the parent.
Code Snippet: Overriding a Parent Method in JavaScript
Let’s say we want to override the getFullName()
method in the Child
class to add the child’s favorite toy to their full name.
// Parent class
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
}
// Child class overriding the getFullName method
class Child extends Person {
constructor(firstName, lastName, favoriteToy) {
super(firstName, lastName);
this.favoriteToy = favoriteToy;
}
// Overriding the parent's method
getFullName() {
return `${this.firstName} ${this.lastName} loves playing with ${this.favoriteToy}.`;
}
play() {
console.log(`${this.getFullName()}`);
}
}
const lucy = new Child("Lucy", "Smith", "Doll");
lucy.play(); // Output: Lucy Smith loves playing with Doll.
Explanation:
The
Child
class overrides thegetFullName()
method from thePerson
class.Even though both the parent and child classes have the same method name (
getFullName()
), the child class version takes precedence when called on an instance ofChild
.
Challenge – Extending the Family Tree with Advanced Inheritance
Let’s reinforce the concept of inheritance by extending your family tree. In this challenge, you’ll create new family members that inherit traits from the Person
class and add some more complexity by overriding methods and introducing custom behaviors.
Challenge Instructions:
Create a
Person
class: This will act as the base parent class. It should have basic properties likefirstName
,lastName
, and a methodgetFullName()
.Create subclasses for
Parent
andChild
: Both should inherit fromPerson
, but add their own unique properties and behaviors. For example,Parent
might override thegetFullName()
method to include a job title, andChild
might override it to include their favorite toy.Extend further: Create other family members like
Grandparent
orSibling
and see how you can reuse and override methods to add more flexibility.
Example:
// Base class
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
}
// Parent class inherits and overrides
class Parent extends Person {
constructor(firstName, lastName, job) {
super(firstName, lastName);
this.job = job;
}
// Overriding getFullName to include the job
getFullName() {
return `${this.firstName} ${this.lastName} works as a ${this.job}.`;
}
work() {
console.log(this.getFullName());
}
}
// Child class inherits and overrides
class Child extends Person {
constructor(firstName, lastName, favoriteGame) {
super(firstName, lastName);
this.favoriteGame = favoriteGame;
}
// Overriding getFullName to include the favorite game
getFullName() {
return `${this.firstName} ${this.lastName} loves playing ${this.favoriteGame}.`;
}
play() {
console.log(this.getFullName());
}
}
// Instances
const father = new Parent("James", "Brown", "Engineer");
const son = new Child("Tom", "Brown", "Chess");
father.work(); // Output: James Brown works as an Engineer.
son.play(); // Output: Tom Brown loves playing Chess.
Conclusion – Extending Functionality Through Inheritance
We’ve explored the deeper workings of inheritance in JavaScript through the prototype chain and learned how to override methods in child classes. You’ve seen how inheritance can make your code more flexible and maintainable by allowing you to share common traits while customizing behavior where needed.
By mastering inheritance, you’re now equipped to build more advanced JavaScript applications with clean, reusable, and scalable code.
Let’s tackle Polymorphism next!
In the next article, we’ll explore polymorphism—an advanced OOP concept that allows objects to be treated as instances of their parent class, giving you even more flexibility in how you design your programs.
Subscribe to my newsletter
Read articles from gayatri kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by