DEV Community

Cover image for Prototypal Inheritance in JavaScript: A Complete Guide with Class-Based Examples ๐Ÿš€
Burhanuddin S. Tinwala
Burhanuddin S. Tinwala

Posted on

Prototypal Inheritance in JavaScript: A Complete Guide with Class-Based Examples ๐Ÿš€

JavaScript is a language full of quirks and power, and one of its most exciting features is prototypal inheritance. If youโ€™ve ever wondered how objects share properties and behaviors in JS, or why classes make inheritance so intuitive, youโ€™re in the right place. Letโ€™s explore this concept with a modern twistโ€”using ES6 Classes and some real-world examples! ๐ŸŒŸ


๐ŸŽ“ What is Prototypal Inheritance?

In JavaScript, prototypal inheritance means that objects can "borrow" properties and methods from other objects via a special chain called the prototype chain. Itโ€™s like passing down the family recipeโ€”one object shares its knowledge with others. ๐Ÿง‘โ€๐Ÿณ

With ES6 Classes, this inheritance process becomes super intuitive, making your code cleaner and easier to read. Classes are essentially syntactic sugar over JavaScript's prototypal inheritance.


๐Ÿ› ๏ธ How Does it Work with Classes?

When you use a class in JavaScript, youโ€™re essentially creating a blueprint. Objects created from this blueprint can inherit properties and methods, making your code reusable and organized.

Hereโ€™s an example to make it click:

// Base class (Parent)
class Vehicle {
  constructor(type, speed) {
    this.type = type; // e.g., "Car", "Bike"
    this.speed = speed; // e.g., 100 km/h
  }

  move() {
    console.log(`๐Ÿš— The ${this.type} is moving at ${this.speed} km/h.`);
  }
}

// Subclass (Child)
class ElectricVehicle extends Vehicle {
  constructor(type, speed, battery) {
    super(type, speed); // Call the parent constructor
    this.battery = battery; // Additional property for EVs
  }

  charge() {
    console.log(`๐Ÿ”‹ The ${this.type} is charging with a ${this.battery} battery.`);
  }
}

// Create instances
const tesla = new ElectricVehicle("Tesla Model 3", 200, "75 kWh");
tesla.move(); // Output: ๐Ÿš— The Tesla Model 3 is moving at 200 km/h.
tesla.charge(); // Output: ๐Ÿ”‹ The Tesla Model 3 is charging with a 75 kWh battery.
Enter fullscreen mode Exit fullscreen mode

Key Concepts in the Example

  1. class Vehicle: The parent class with common properties and methods.
  2. class ElectricVehicle extends Vehicle: The child class inherits from the parent class using extends.
  3. super(): Calls the parent class's constructor, so the child class can use its properties and methods.

๐ŸŒŸ Real-World Use Cases

1. A Library System ๐Ÿ“š

Imagine you're building a library app where users can borrow physical and eBooks.

class Book {
  constructor(title, author) {
    this.title = title;
    this.author = author;
  }

  read() {
    console.log(`๐Ÿ“– Reading "${this.title}" by ${this.author}.`);
  }
}

class EBook extends Book {
  constructor(title, author, fileSize) {
    super(title, author);
    this.fileSize = fileSize;
  }

  download() {
    console.log(`๐Ÿ’พ Downloading "${this.title}" (${this.fileSize}MB)...`);
  }
}

// Create instances
const physicalBook = new Book("The Hobbit", "J.R.R. Tolkien");
physicalBook.read(); // Output: ๐Ÿ“– Reading "The Hobbit" by J.R.R. Tolkien.

const digitalBook = new EBook("The Hobbit", "J.R.R. Tolkien", 15);
digitalBook.read(); // Output: ๐Ÿ“– Reading "The Hobbit" by J.R.R. Tolkien.
digitalBook.download(); // Output: ๐Ÿ’พ Downloading "The Hobbit" (15MB)...
Enter fullscreen mode Exit fullscreen mode

2. A Food Delivery App ๐Ÿ•

For a food delivery app, you might have different types of orders like regular and subscription-based.

class Order {
  constructor(orderId, items) {
    this.orderId = orderId;
    this.items = items; // List of items in the order
  }

  calculateTotal() {
    return this.items.reduce((total, item) => total + item.price, 0);
  }
}

class SubscriptionOrder extends Order {
  constructor(orderId, items, deliveryFrequency) {
    super(orderId, items);
    this.deliveryFrequency = deliveryFrequency; // e.g., Weekly, Monthly
  }

  displayDetails() {
    console.log(
      `๐Ÿ“ฆ Order #${this.orderId}: Total $${this.calculateTotal()} (Delivered ${this.deliveryFrequency})`
    );
  }
}

// Create instances
const order = new Order(1, [
  { name: "Pizza", price: 10 },
  { name: "Soda", price: 2 },
]);
console.log(`๐Ÿงพ Total: $${order.calculateTotal()}`); // Output: ๐Ÿงพ Total: $12

const subscriptionOrder = new SubscriptionOrder(2, [
  { name: "Salad", price: 8 },
  { name: "Juice", price: 4 },
], "Weekly");
subscriptionOrder.displayDetails(); // Output: ๐Ÿ“ฆ Order #2: Total $12 (Delivered Weekly)
Enter fullscreen mode Exit fullscreen mode

๐ŸŽฏ Benefits of Using Classes for Prototypal Inheritance

  1. Clarity and Readability โœ๏ธ

    The class syntax is clean and structured, making your code easier to understand.

  2. Encapsulation of Logic ๐Ÿ”

    Keep related properties and methods together in a single blueprint.

  3. Extendable Design ๐Ÿ› ๏ธ

    With extends and super, you can create hierarchies that naturally reflect real-world relationships.

  4. Modern Best Practices โœ…

    ES6 classes are widely supported and encouraged in modern JavaScript development.


๐Ÿ“Œ Takeaways

Prototypal inheritance is at the heart of JavaScriptโ€™s object model, and using ES6 classes makes it both elegant and intuitive. Whether youโ€™re building a library app, a food delivery platform, or anything in between, understanding how to leverage inheritance will make your code cleaner and more efficient.

So, the next time you create an app, think about how you can use prototypal inheritance to keep your code DRY (Donโ€™t Repeat Yourself)! ๐Ÿ’ก

๐Ÿ’ฌ Got questions or want more examples? Drop a comment below!

Let's connect LinkedIn

Top comments (0)