# JavaScript Prototypes – Understanding Prototypal Inheritance

Yesterday, I learned about **Object-Oriented Programming in JavaScript**, including classes, constructors, methods, inheritance, and the `this` keyword.

Today, I went deeper into how JavaScript actually implements inheritance.

The key concept is **Prototypes**.

JavaScript isn't fundamentally a class-based language like Java or C++. It uses a **prototype-based object model**.

Modern `class` syntax makes object-oriented programming easier to write, but underneath the surface, JavaScript still relies on prototypes.

Let's dive in.

* * *

# What is a Prototype?

Every JavaScript object has an internal link to another object called its **prototype**.

That prototype can provide properties and methods that the object can access.

For example:

```javascript
const user = {
    name: "Saurabh"
};

console.log(user.toString());
```

We didn't define `toString()` inside `user`.

So where did it come from?

JavaScript looks up the object's prototype and finds the method there.

This is called **prototype inheritance**.

* * *

# Prototype Chain

When JavaScript tries to access a property or method, it first checks the object itself.

If it doesn't find it, JavaScript looks at the object's prototype.

If it still doesn't find it, JavaScript continues searching up the prototype chain.

Conceptually:

```text
Object
   ↓
Prototype
   ↓
Prototype's Prototype
   ↓
null
```

This is called the **prototype chain**.

* * *

# Object.prototype

Most ordinary JavaScript objects ultimately inherit from:

```javascript
Object.prototype
```

For example:

```javascript
const user = {
    name: "Saurabh"
};

console.log(
    Object.getPrototypeOf(user)
);
```

The result is the object's prototype, which for an object literal is generally `Object.prototype`.

* * *

# Object.getPrototypeOf()

We can inspect an object's prototype using:

```javascript
Object.getPrototypeOf(user);
```

Example:

```javascript
const user = {
    name: "Saurabh"
};

console.log(
    Object.getPrototypeOf(user)
);
```

This is useful for understanding the prototype chain.

* * *

# The `__proto__` Property

You may also encounter:

```javascript
user.__proto__
```

This accesses the object's prototype through a legacy accessor.

Although you'll see it frequently while learning JavaScript, `Object.getPrototypeOf()` **and** `Object.setPrototypeOf()` **are generally preferred for explicit prototype manipulation**.

For example:

```javascript
console.log(
    Object.getPrototypeOf(user)
);
```

* * *

# Constructor Functions

Before `class` syntax became common, JavaScript developers frequently used **constructor functions** to create similar objects.

Example:

```javascript
function User(name, age) {

    this.name = name;

    this.age = age;

}
```

We can create objects using:

```javascript
const user1 = new User(
    "Saurabh",
    22
);

const user2 = new User(
    "Rahul",
    23
);
```

The `new` keyword connects these objects to:

```javascript
User.prototype
```

* * *

# Adding Methods to a Prototype

Instead of creating a new copy of a method for every instance, we can place the method on the constructor's prototype.

```javascript
User.prototype.greet = function () {

    console.log(
        `Hello ${this.name}`
    );

};
```

Now:

```javascript
user1.greet();

user2.greet();
```

Both objects can use the same prototype method.

* * *

# Why Use the Prototype?

Consider this:

```javascript
function User(name) {

    this.name = name;

    this.greet = function () {
        console.log(
            `Hello ${this.name}`
        );
    };

}
```

Every time we create a new User, a new function is created for `greet`.

Instead:

```javascript
function User(name) {

    this.name = name;

}

User.prototype.greet = function () {

    console.log(
        `Hello ${this.name}`
    );

};
```

Now the method is shared through the prototype.

This is one of the important ideas behind JavaScript's prototype system.

* * *

# Checking the Prototype

We can verify the relationship:

```javascript
console.log(
    Object.getPrototypeOf(user1) === User.prototype
);
```

Output:

```text
true
```

This tells us that `user1` is linked to `User.prototype`.

* * *

# Prototype Chain Lookup

Suppose:

```javascript
const user = {
    name: "Saurabh"
};
```

We run:

```javascript
user.toString();
```

JavaScript roughly searches like this:

```text
Does user have toString?
        ↓
       No
        ↓
Does user.__proto__ have toString?
        ↓
       Yes
        ↓
Execute it
```

This lookup process is fundamental to understanding JavaScript inheritance.

* * *

# Constructor's Prototype Property

Functions used as constructors have a `.prototype` property.

Example:

```javascript
function User(name) {

    this.name = name;

}

console.log(User.prototype);
```

We can add methods:

```javascript
User.prototype.greet = function () {

    console.log(
        `Hello ${this.name}`
    );

};
```

When an object is created with:

```javascript
const user = new User("Saurabh");
```

the object's prototype is connected to:

```javascript
User.prototype
```

* * *

# Class Syntax and Prototypes

This is where yesterday's lesson connects with today's.

When we write:

```javascript
class User {

    greet() {

        console.log("Hello");

    }

}
```

the method isn't simply copied separately into every instance.

The class's methods are placed on:

```javascript
User.prototype
```

So:

```javascript
const user = new User();

console.log(
    Object.getPrototypeOf(user) === User.prototype
);
```

returns:

```text
true
```

This is why understanding prototypes helps explain what JavaScript classes are actually doing.

* * *

# Prototypal Inheritance

Objects can inherit from other objects.

One way to create such a relationship is:

```javascript
const animal = {

    speak() {

        console.log("Animal sound");

    }

};
```

Create another object based on it:

```javascript
const dog = Object.create(animal);
```

Now:

```javascript
dog.speak();
```

The `dog` object doesn't have its own `speak()` method.

JavaScript finds it through its prototype.

* * *

# Object.create()

`Object.create()` allows us to create a new object with a specified prototype.

Example:

```javascript
const vehicle = {

    start() {

        console.log("Vehicle started");

    }

};

const car = Object.create(vehicle);

car.start();
```

The prototype relationship is:

```text
car
 ↓
vehicle
 ↓
Object.prototype
 ↓
null
```

* * *

# Prototype Inheritance With Constructors

We can also create inheritance between constructor prototypes.

```javascript
function Animal(name) {

    this.name = name;

}

Animal.prototype.speak = function () {

    console.log(
        `${this.name} makes a sound`
    );

};
```

Now create a `Dog` constructor:

```javascript
function Dog(name, breed) {

    Animal.call(this, name);

    this.breed = breed;

}
```

Connect the prototypes:

```javascript
Dog.prototype = Object.create(
    Animal.prototype
);

Dog.prototype.constructor = Dog;
```

Now add a Dog-specific method:

```javascript
Dog.prototype.bark = function () {

    console.log(
        `${this.name} says Woof!`
    );

};
```

Create the object:

```javascript
const dog = new Dog(
    "Bruno",
    "Labrador"
);

dog.speak();

dog.bark();
```

The dog can access methods from the `Animal` prototype.

* * *

# `hasOwnProperty()`

Sometimes we need to determine whether a property belongs directly to an object or is inherited.

Example:

```javascript
const user = {
    name: "Saurabh"
};

console.log(
    user.hasOwnProperty("name")
);
```

Output:

```text
true
```

But:

```javascript
console.log(
    user.hasOwnProperty("toString")
);
```

returns:

```text
false
```

because `toString` is inherited rather than an own property.

* * *

# Own Properties vs Inherited Properties

Consider:

```javascript
const user = {
    name: "Saurabh"
};
```

### Own property

```text
name
```

belongs directly to `user`.

### Inherited property

```text
toString
```

comes from the prototype chain.

This distinction becomes useful when inspecting and debugging objects.

* * *

# Prototype vs `__proto__`

These two terms are often confused.

### `.prototype`

Usually refers to the property on a constructor function that becomes the prototype of instances created with `new`.

```javascript
User.prototype
```

### `[[Prototype]]`

The internal prototype link of an object.

We can access it using:

```javascript
Object.getPrototypeOf(user)
```

The legacy:

```javascript
user.__proto__
```

also exposes that link, but it is generally better to use the standard `Object.getPrototypeOf()` API.

* * *

# Best Practices

✔ Understand prototypes even if you primarily use `class` syntax.

✔ Prefer `Object.getPrototypeOf()` over relying on `__proto__`.

✔ Use prototypes for shared behavior when working with constructor functions.

✔ Don't modify built-in prototypes such as `Array.prototype` in normal application code.

✔ Use `class` syntax when it makes your application's object model easier to understand.

✔ Remember that JavaScript's `class` syntax is built on the prototype system.

* * *

# My Biggest Takeaway

Today, I learned what's happening **underneath JavaScript classes**.

The biggest realization was:

**JavaScript classes are built on top of prototypes.**

When I create an instance:

```javascript
const user = new User();
```

the object can access methods through:

```text
user
 ↓
User.prototype
 ↓
Object.prototype
 ↓
null
```

Understanding this prototype chain makes JavaScript's inheritance model much clearer.
