# Understanding Prototypes & Inheritance in JavaScript: The Blueprint Analogy

Ever wondered how JavaScript objects share behaviors and properties? Let me take you on a journey through one of JavaScript's most powerful yet misunderstood features: prototypes and inheritance.

## The Blueprint Story: Understanding Prototypes

Imagine you're an architect designing houses. You don't build each house from scratch—you create a **blueprint** that contains all the common features: doors, windows, plumbing systems. Each house built from this blueprint shares these features, but can also have its own unique characteristics.

This is exactly how JavaScript prototypes work!

```javascript
// The "Blueprint" - Constructor Function
function House(address, color) {
    this.address = address;
    this.color = color;
}

// Shared features (methods) on the prototype
House.prototype.openDoor = function() {
    console.log(`Opening door at ${this.address}`);
};

House.prototype.paintWall = function(newColor) {
    this.color = newColor;
    console.log(`House painted ${newColor}`);
};

// Creating houses from the blueprint
const house1 = new House("123 Main St", "blue");
const house2 = new House("456 Oak Ave", "red");

house1.openDoor(); // "Opening door at 123 Main St"
house2.openDoor(); // "Opening door at 456 Oak Ave"
```

### What Happens When Two Objects Are Created from One Class?

When you create `house1` and `house2` from the same constructor:

1. **Each object gets its own property storage** - `house1.address` and `house2.address` are separate
    
2. **They share the same prototype methods** - Both point to `House.prototype.openDoor` (same memory location!)
    
3. **Changes to the prototype affect all instances**
    

```javascript
console.log(house1.openDoor === house2.openDoor); // true (same function!)

// Adding a new method to the prototype
House.prototype.lockDoor = function() {
    console.log(`Locking door at ${this.address}`);
};

// Both houses can now use it!
house1.lockDoor(); // Works!
house2.lockDoor(); // Works!
```

## The Prototype Chain: The Family Tree

Think of prototypes like a **family tree of genetic traits**. Your traits come from your parents, their traits come from grandparents, and so on.

```plaintext
house1 → House.prototype → Object.prototype → null
```

```javascript
// Demonstration of the prototype chain
console.log(house1.toString()); // Inherited from Object.prototype

// The chain lookup process
house1.openDoor();
// 1. Does house1 have openDoor? No
// 2. Does House.prototype have openDoor? Yes! Execute it.
```

## `prototype` vs `__proto__`: The Confusion Cleared

This is where many developers get confused. Let's break it down with our blueprint analogy:

* `prototype`: The blueprint itself (only on constructor functions)
    
* `__proto__`: The reference each house keeps to its blueprint
    

```javascript
function Animal(name) {
    this.name = name;
}

Animal.prototype.speak = function() {
    console.log(`${this.name} makes a sound`);
};

const dog = new Animal("Rex");

// PROTOTYPE - the blueprint (only on constructor)
console.log(typeof Animal.prototype); // "object"
console.log(Animal.prototype.speak); // function

// __PROTO__ - the reference to the blueprint (on instances)
console.log(dog.__proto__ === Animal.prototype); // true
console.log(dog.prototype); // undefined (instances don't have prototype)
```

### Visual Comparison: `prototype` vs `__proto__`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1766943710881/eb42bbde-b471-4709-b2a1-c87d1412a4b5.jpeg align="center")

## What Does `new` Really Do?

The `new` keyword is like a house-building robot. Let's see what it does step by step:

```javascript
function Car(brand, model) {
    this.brand = brand;
    this.model = model;
}

Car.prototype.drive = function() {
    console.log(`${this.brand} ${this.model} is driving`);
};

const myCar = new Car("Toyota", "Camry");
```

When you use `new Car("Toyota", "Camry")`, JavaScript does this:

```javascript
// What 'new' does behind the scenes:
function simulateNew(Constructor, ...args) {
    // 1. Create a new empty object
    const obj = {};
    
    // 2. Set the object's __proto__ to Constructor.prototype
    obj.__proto__ = Constructor.prototype;
    // or: Object.setPrototypeOf(obj, Constructor.prototype);
    
    // 3. Execute the constructor with 'this' bound to the new object
    const result = Constructor.apply(obj, args);
    
    // 4. Return the object (unless constructor returns its own object)
    return result instanceof Object ? result : obj;
}

const myCar2 = simulateNew(Car, "Honda", "Civic");
myCar2.drive(); // "Honda Civic is driving"
```

## Inheritance Without `extends`: The Old-School Way

Before ES6 classes, JavaScript developers achieved inheritance using prototypes directly. It's like creating a specialized blueprint that builds upon a general one.

### Method 1: Using `Object.create()`

```javascript
// Parent "class"
function Vehicle(type) {
    this.type = type;
    this.speed = 0;
}

Vehicle.prototype.accelerate = function(amount) {
    this.speed += amount;
    console.log(`${this.type} accelerating to ${this.speed} mph`);
};

// Child "class"
function Motorcycle(type, brand) {
    // Call parent constructor
    Vehicle.call(this, type);
    this.brand = brand;
}

// Set up inheritance - Create prototype chain
Motorcycle.prototype = Object.create(Vehicle.prototype);
Motorcycle.prototype.constructor = Motorcycle;

// Add child-specific methods
Motorcycle.prototype.wheelie = function() {
    console.log(`${this.brand} ${this.type} doing a wheelie!`);
};

const myBike = new Motorcycle("Motorcycle", "Harley");
myBike.accelerate(50); // "Motorcycle accelerating to 50 mph"
myBike.wheelie(); // "Harley Motorcycle doing a wheelie!"
```

### Method 2: Manual Prototype Assignment

```javascript
function Animal(name) {
    this.name = name;
}

Animal.prototype.eat = function() {
    console.log(`${this.name} is eating`);
};

function Dog(name, breed) {
    Animal.call(this, name);
    this.breed = breed;
}

// Create the inheritance link
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
    console.log(`${this.name} the ${this.breed} says Woof!`);
};

const buddy = new Dog("Buddy", "Golden Retriever");
buddy.eat();  // "Buddy is eating" (inherited)
buddy.bark(); // "Buddy the Golden Retriever says Woof!"
```

### The Prototype Chain Visualization

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1766943961062/cc722379-fca8-49b4-8b01-de76b6d42f2a.jpeg align="center")

## Events in JavaScript: The Party Invitation Analogy

JavaScript events are like sending party invitations through an apartment building. Let's understand this with a real-world analogy.

### The Apartment Building Model

Imagine an apartment building with floors and apartments:

* **Building** = `<html>`
    
* **Floor** = `<body>` or `<div>`
    
* **Apartment** = `<button>` or `<input>`
    

When you knock on an apartment door (click a button), three things happen:

1. **Capturing Phase**: The sound travels DOWN from the building entrance to your apartment
    
2. **Target Phase**: You answer the door
    
3. **Bubbling Phase**: The sound travels UP back through the building
    

### Event Propagation Code Example

```javascript
// HTML structure (conceptually):
// <div id="building">
//   <div id="floor">
//     <button id="apartment">Click Me</button>
//   </div>
// </div>

const building = document.getElementById('building');
const floor = document.getElementById('floor');
const apartment = document.getElementById('apartment');

// CAPTURING PHASE (going down) - set third parameter to true
building.addEventListener('click', function() {
    console.log('1. Building heard the knock (capturing)');
}, true);

floor.addEventListener('click', function() {
    console.log('2. Floor heard the knock (capturing)');
}, true);

// TARGET PHASE
apartment.addEventListener('click', function(event) {
    console.log('3. Apartment answers! (target)');
    // event.stopPropagation(); // Stop the sound from traveling
});

// BUBBLING PHASE (going up) - default behavior
floor.addEventListener('click', function() {
    console.log('4. Floor heard the answer (bubbling)');
});

building.addEventListener('click', function() {
    console.log('5. Building heard the answer (bubbling)');
});

// When you click the button, output:
// 1. Building heard the knock (capturing)
// 2. Floor heard the knock (capturing)
// 3. Apartment answers! (target)
// 4. Floor heard the answer (bubbling)
// 5. Building heard the answer (bubbling)
```

### Event Delegation: The Receptionist Pattern

Instead of hiring a receptionist for each apartment, hire ONE receptionist at the building entrance who handles all deliveries.

```javascript
// BAD: Adding listener to each button (like hiring many receptionists)
document.querySelectorAll('.apartment').forEach(button => {
    button.addEventListener('click', handleClick);
});

// GOOD: Event delegation (one receptionist for the building)
document.getElementById('building').addEventListener('click', function(event) {
    if (event.target.classList.contains('apartment')) {
        console.log(`Package delivered to apartment ${event.target.id}`);
    }
});
```

### Common Event Methods

```javascript
element.addEventListener('click', function(event) {
    // Stop bubbling up
    event.stopPropagation();
    
    // Prevent default behavior (like form submission)
    event.preventDefault();
    
    // Who was clicked?
    console.log(event.target);
    
    // Who is listening?
    console.log(event.currentTarget);
    
    // Where in the journey?
    console.log(event.eventPhase); // 1=capturing, 2=target, 3=bubbling
});
```

## Practical Example: Building a Shape Hierarchy

Let's combine everything we've learned into a practical example:

```javascript
// Base Shape "class"
function Shape(color) {
    this.color = color;
}

Shape.prototype.describe = function() {
    console.log(`A ${this.color} shape`);
};

// Circle inherits from Shape
function Circle(color, radius) {
    Shape.call(this, color); // Inherit properties
    this.radius = radius;
}

Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;

Circle.prototype.area = function() {
    return Math.PI * this.radius ** 2;
};

Circle.prototype.describe = function() {
    console.log(`A ${this.color} circle with radius ${this.radius}`);
};

// Rectangle inherits from Shape
function Rectangle(color, width, height) {
    Shape.call(this, color);
    this.width = width;
    this.height = height;
}

Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

Rectangle.prototype.area = function() {
    return this.width * this.height;
};

Rectangle.prototype.describe = function() {
    console.log(`A ${this.color} rectangle ${this.width}x${this.height}`);
};

// Usage
const circle = new Circle("red", 5);
const rectangle = new Rectangle("blue", 4, 6);

circle.describe(); // "A red circle with radius 5"
console.log(circle.area()); // 78.54

rectangle.describe(); // "A blue rectangle 4x6"
console.log(rectangle.area()); // 24

// Both are shapes!
console.log(circle instanceof Circle);    // true
console.log(circle instanceof Shape);     // true
console.log(rectangle instanceof Shape);  // true
```

## Key Takeaways

1. **Prototypes are blueprints** - They define shared behavior for objects
    
2. `prototype` is on constructors - The blueprint itself
    
3. `__proto__` is on instances - The reference to the blueprint
    
4. `new` creates and links - It builds the object and sets up the prototype chain
    
5. **Inheritance without** `extends` - Use `Object.create()` and `.call()` for classical inheritance
    
6. **Events flow in three phases** - Capturing → Target → Bubbling
    

## Modern JavaScript Note

While understanding prototypes is crucial, modern JavaScript (ES6+) provides the `class` syntax as syntactic sugar:

```javascript
class Vehicle {
    constructor(type) {
        this.type = type;
    }
    
    accelerate() {
        console.log(`${this.type} is accelerating`);
    }
}

class Motorcycle extends Vehicle {
    constructor(type, brand) {
        super(type);
        this.brand = brand;
    }
    
    wheelie() {
        console.log(`${this.brand} doing a wheelie!`);
    }
}
```

Under the hood, this still uses prototypes! The `class` syntax just makes it cleaner and more familiar to developers from other languages.

---

**Remember**: JavaScript's prototype system is like genetic inheritance—objects inherit traits from their prototypes, creating a chain of shared behaviors that makes code efficient and elegant. Master this, and you'll truly understand JavaScript's object-oriented nature!

What aspect of prototypes or events would you like to explore deeper? Drop your questions in the comments below! 🚀
