πŸš€ Prototypes & Prototypal Inheritance in JS: 
 Let's Learn Together (and Nail That Interview 🎯)

πŸš€ Prototypes & Prototypal Inheritance in JS: Let's Learn Together (and Nail That Interview 🎯)

Β·

7 min read

πŸ› οΈ What are Prototypes?

In JavaScript, objects can inherit πŸ—οΈ properties and methods from other objects using prototypes πŸ”—.


πŸ“Œ Key Points:

βœ”οΈ Every object in JavaScript has a special property called a prototype 🏷️.

βœ”οΈ This prototype is itself another object 🧩 and can have its own prototype.

βœ”οΈ This forms a prototype chain πŸ”—, where objects inherit features from one another.

βœ”οΈ The prototype chain ends 🚫 when an object’s prototype is null (meaning no further inheritance β›”).

πŸ” Understanding Prototype with an Example πŸ€”

πŸ‘‹ Example 1: Using Prototype to Add Methods πŸ› οΈ

// Constructor function
function Person(name, age) {
    this.name = name;
    this.age = age;
}

// Adding a method to Person's prototype
Person.prototype.greet = function() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old. πŸ™‹β€β™‚οΈ`);
};

// Creating instances of Person
const person1 = new Person("Saurabh", 28);
const person2 = new Person("John", 30);

// Calling the method from prototype
person1.greet(); // Output: Hello, my name is Saurabh and I am 28 years old. πŸ™‹β€β™‚οΈ
person2.greet(); // Output: Hello, my name is John and I am 30 years old. πŸ™‹β€β™‚οΈ

Here, the greet method is added to Person.prototype, meaning all instances of Person can access it without duplicating the method in each instance. πŸ”


πŸ”— Example 2: Checking the Prototype Chain πŸ”

console.log(person1.__proto__ === Person.prototype); // true βœ…
console.log(Person.prototype.__proto__ === Object.prototype); // true βœ…
console.log(Object.prototype.__proto__); // null ❌

This shows:

  1. person1's prototype is Person.prototype. πŸ’Ό

  2. Person.prototype inherits from Object.prototype. 🌍

  3. Object.prototype has no further prototype (its __proto__ is null). 🚫


πŸš€ Key Points about Prototype in JavaScript πŸ“š

  1. Every function in JavaScript has a prototype property, which is an object. πŸ§‘β€πŸ’»

  2. Objects created from a constructor function inherit properties and methods from that constructor's prototype. πŸ”„

  3. Prototype-based inheritance allows memory-efficient sharing of methods. πŸ§ πŸ’Ύ

  4. The prototype chain helps us look up properties/methods in parent objects. πŸ”—


🐾 Understanding Prototypes with Dog and Animal Example 🐢

Let’s break it down step-by-step using the Animal (Parent) and Dog (Child) objects. 🐾


πŸ”‘ Key Concepts:

  1. Parent (Prototype) - Animal 🦁
    The Animal object has some properties and methods that all animals (including dogs) will have. This acts like a template for all animals.

     const Animal = {
       type: "Animal", // Type of animal
       eats: true,      // All animals eat
       makeSound: function() { // Generic sound
         console.log("Generic animal sound");
       }
     };
    
  2. Child (Object inheriting from Animal) - Dog πŸ•
    The Dog object inherits all properties and methods from Animal using Object.create(). Dogs have their own properties and can override the inherited methods.

     const Dog = Object.create(Animal); // Dog inherits from Animal
     Dog.breed = "Golden Retriever";    // Dog's own property
     Dog.makeSound = function() {       // Dog's own sound
       console.log("Woof!");            // Overrides the inherited sound
     };
    

🎬 How It Works:

  1. Inheriting Properties from Animal 🦁:

    • Dog inherits the type and eats properties from Animal.
    console.log(Dog.type);  // Output: "Animal" (inherited)
    console.log(Dog.eats);  // Output: true (inherited)
  1. Dog's Own Property 🐾:

    • The Dog has its own property breed.
    console.log(Dog.breed);  // Output: "Golden Retriever" (Dog's own property)
  1. Overriding a Method 🎀:

    • The Dog overrides the inherited makeSound method to make its own unique sound, "Woof!" 🐢.
    Dog.makeSound(); // Output: "Woof!" (Dog's own method overrides Animal's)
  1. Prototype Chain πŸ”—:

    • Animal.isPrototypeOf(Dog) checks if Animal is in the prototype chain of Dog. Since Dog inherits from Animal, it returns true.
    console.log(Animal.isPrototypeOf(Dog));  // Output: true (Animal is prototype of Dog)

πŸ“ Summary:

  • Dog πŸ• inherits type and eats from Animal 🦁, but can also have its own properties like breed.

  • Dog πŸ• can override the inherited makeSound method to make its unique sound, "Woof!" 🐾.

  • Prototype chain πŸ”— allows objects to inherit properties and methods, making code more reusable and efficient.


🏠 Real-World Analogy: Car and ElectricCar πŸš—βš‘

Imagine we have a Car (parent) object that has properties and methods for any car. Then, we have an ElectricCar (child) object that inherits from the Car object but also has its own properties, like being electric.


πŸš— Parent (Prototype) - Car

The Car object is the base prototype with general properties and methods that all cars will have.

// Parent (Prototype)
const Car = {
  type: "Car",           // Type of vehicle
  wheels: 4,             // All cars have 4 wheels
  fuel: "Gasoline",      // Cars use gasoline (default)
  startEngine: function() { // All cars can start their engine
    console.log("Engine started πŸ”‘");
  }
};

⚑ Child (Object inheriting from Car) - ElectricCar

The ElectricCar object inherits the properties and methods from Car but can also add its own features, like using electricity instead of gasoline πŸ”‹βš‘.

// Child (Object inheriting from Car)
const ElectricCar = Object.create(Car);

// Adding ElectricCar's own property
ElectricCar.battery = "Lithium-ion battery πŸ”‹";

// Overriding the fuel property and method
ElectricCar.fuel = "Electricity ⚑";
ElectricCar.startEngine = function() {
  console.log("Electric engine started πŸ”‹βš‘");
};

🎬 How It Works:

  1. Inheriting Properties from Car πŸš—:

    • The ElectricCar inherits the type, wheels, and fuel properties from Car.
    console.log(ElectricCar.type);   // Output: "Car" (inherited from Car)
    console.log(ElectricCar.wheels); // Output: 4 (inherited from Car)
    console.log(ElectricCar.fuel);   // Output: "Electricity ⚑" (overridden by ElectricCar)
  1. ElectricCar's Own Property πŸ”‹:

    • The ElectricCar has its own property battery.
    console.log(ElectricCar.battery); // Output: "Lithium-ion battery πŸ”‹" (ElectricCar's own property)
  1. Overriding a Method ⚑:

    • The ElectricCar overrides the startEngine method to reflect the electric engine start.
    ElectricCar.startEngine(); // Output: "Electric engine started πŸ”‹βš‘" (ElectricCar's custom method)
  1. Prototype Chain πŸ”—:

    • The Car object is still in the prototype chain of ElectricCar. So, ElectricCar can access all the inherited properties and methods from Car.
    console.log(Car.isPrototypeOf(ElectricCar)); // Output: true (Car is prototype of ElectricCar)

πŸ“ Summary:

  • The ElectricCar 🏎️ inherits properties like type, wheels, and fuel from Car πŸš—, but it can override the fuel property and the startEngine method to fit its electric nature ⚑.

  • ElectricCar also adds its own property, battery, to reflect its specific feature πŸ”‹.

This is how prototype inheritance allows objects to share properties and methods, while also enabling customization and extensions! πŸŽ‰


πŸ“ Conclusion:

  1. Inheritance and Prototypes in JavaScript:

    • Prototypes are like a family tree 🌳 in JavaScript. They allow objects to inherit properties and methods from other objects, saving you from repeating code and making it more reusable and efficient. ⚑
  2. Example 1: Animal and Dog πŸ¦πŸ•:

    • The Dog inherits general properties like type and eats from its parent, Animal. But it can also add its own properties like breed and override methods (e.g., makeSound) to be more specific to Dog. This shows how an object can extend and customize the features it inherits.

    • This is like a child inheriting basic traits (e.g., eating) from their parents but also gaining their own unique skills (like dancing or playing the guitar) 🎸.

  3. Example 2: Car and ElectricCar πŸš—βš‘:

    • The ElectricCar inherits general properties like wheels and fuel from the Car prototype. It then overrides the fuel to be Electricity and changes the startEngine method to reflect its electric engine. The ElectricCar also adds its own property (battery) to reflect its unique feature.

    • This is similar to a child inheriting characteristics from a parent (like the number of wheels) but adapting and adding new features (like an electric engine) to make it their own.


πŸ’‘ Key Takeaways:

  • Prototypes allow objects to inherit properties and methods, avoid duplication, and enable code reuse.

  • Objects can override inherited methods and add their own properties to extend or customize their behavior.

  • The prototype chain links objects together, forming a hierarchical structure where each object can inherit from its parent and its parent’s parent, up to the top (usually Object.prototype).

This is the magic of inheritance in JavaScript! It helps you write cleaner, more organized code while keeping things modular and flexible. πŸš€


Β