How __Proto__, Prototype, and Inheritance Actually Work in JavaScript

by SkillAiNest

Have you ever thought that everything in JavaScript works like an object? Or how inheritance actually works behind the scenes? What is the difference between __proto__ And prototype?

If these questions have crossed your mind, you’re not alone. These are some of the most basic JavaScript concepts, yet they often confuse developers.

In this tutorial, we’ll cover prototypes, prototype chains, and inheritance in JavaScript. Finally, you’ll understand the “what,” “why,” and “how” of JavaScript’s prototype system.

Here is what I will cover:

Conditions

To get the most out of this tutorial, you should:

  • Basic understanding of JavaScript fundamentals

  • Familiarity with objects, functions and classes in JavaScript

  • Knowledge of how to declare and use variables

  • Experience working with new Keyword (helpful but not required)

The String Method Mystery

Let’s start with a simple example that shows something interesting about JavaScript:

let name = "Shejan Mahamud";

After declaring this variable, we can use string methods like:

name.toLowerCase(); 
name.toUpperCase(); 

It seems normal at first glance, but wait – something unusual is happening. Notice something strange here? We are using dot notation on string primitives.

Here’s the surprising part: We know that strings are primitive types in JavaScript, not objects. So how can we use dot notation to access methods? However, dot notation generally only works with objects.

The answer to this mystery lies in understanding how JavaScript handles primitives and prototypes. But before we get there, let’s first look at how objects work internally.

How objects work internally

When you create an object in JavaScript like this:

const info1 = {
  fName: "Shejan",
  lName: "Mahamud"
};

JavaScript does some interesting work behind the scenes. It automatically adds a hidden property called __proto__ This property points to your object Object.prototypewhich is the prototype of the built-in Object class.

You might be surprised: it does Object.prototype There is also a __proto__? Yes, it does, but it’s worth it null. This is the reason Object.prototype The prototype is at the top of the chain and does not inherit from anything else.

Let’s look at a more complicated example to understand this better:

const info1 = {
  fName1: "Shejan",
  lName1: "Mahamud"
};

const info2 = {
  fName2: "Boltu",
  lName2: "Mia",
  __proto__: info1
};

const info3 = {
  fName3: "Habu",
  lName3: "Mia",
  __proto__: info2
};

In this example, we have intentionally set __proto__ property for info2 And info3. Now here’s an interesting question: Can we get access? fName1 from info3?

console.log(info3.fName1); 

Yes, we can! Let’s understand how it works.

Understanding the prototype chain

When you try to access a property on an object, JavaScript follows a specific lookup process:

  1. First, it looks for the property in the object itself (the base object).

  2. If it’s not found there, it looks in the object __proto__

  3. If it still doesn’t find it, it continues, checking each one __proto__ Until he either finds or reaches the property null

With our example info3.fName1:

  • JavaScript sees first info3 – And it doesn’t get it fName1

  • Then it checks info3.__proto__which refers to info2 – It is not found fName1 There, either

  • Next it checks info2.__proto__which refers to info1 – And it gets it fName1 Here!

It is called Prototype chainand that’s how inheritance works in JavaScript. Here is a visual representation:

┌────────────┐
│  info3     │
│ fName3     │
│ lName3     │
└────┬───────┘
     │ __proto__
     ▼
┌────────────┐
│  info2     │
│ fName2     │
│ lName2     │
└────┬───────┘
     │ __proto__
     ▼
┌────────────┐
│  info1     │
│ fName1     │
│ lName1     │
└────┬───────┘
     │ __proto__
     ▼
┌─────────────────┐
│ Object.prototype│
└────┬────────────┘
     ▼
    null

Each object points through it to the next object in the chain __proto__ property This chain continues until it is reached null.

Why is everything an object in JavaScript?

Now let’s solve the mystery we started with: How can primitive types use object methods?

In JavaScript, almost everything behaves like an object, although primitive types (such as string, number, and boolean) aren’t technically objects. It works through a process called Autoboxing or The wrapper object.

Let’s see this in action:

let yourName = "Boltu";

When you try to use a method on this string:

yourName.toLowerCase();

Here’s what JavaScript does behind the scenes:

  1. This temporarily wraps the primitive value in a wrapper object: new String("Boltu")

  2. This is a temporary object __proto__ automatically points to it String.prototype

  3. found in the method String.prototype And executed

  4. After the operation completes, the wrapper object is discarded

  5. yourName Returns to be a simple primitive value

This is why you can use methods on primitives even though they are not objects. JavaScript creates a temporary object, uses it to access a method, then disposes of it.

The same process occurs with other archetypes:

And so this elegant system is why developers often say that “everything in JavaScript is an object” – even when it’s not technically true, it behaves that way when needed.

The difference between __proto__ And prototype

This is the most confusing aspect of JavaScript for many developers. Let’s break it down clearly.

what is prototype?

When you create a function or class in JavaScript, the language automatically creates a blueprint object called prototype. It happens behind the scenes.

Here is an example:

function Person(name) {
  this.name = name;
}

When JavaScript sees this function, it does this internally:

Person.prototype = { 
  constructor: Person 
};

Person The function now has a hidden property called prototypewhich is an object that contains constructor Property

You can add methods to this prototype object:

Person.prototype.sayHi = function() {
  console.log("Hi, I'm " + this.name);
};

what is __proto__?

__proto__ is a property that exists on everything (arrays, functions, objects – everything). It is an internal reference or pointer that indicates which prototype the object inherits from.

By default, when you create an object, its __proto__ On to the points Object.prototype.

How do they work together?

When you use new Keyword:

const p1 = new Person("Shejan");

JavaScript performs these steps internally:

  1. Creates a new empty object: p1 = {}

  2. Specifies the object __proto__: p1.__proto__ = Person.prototype

  3. calls the constructor function with the new object: Person.call(p1, "Shejan")

  4. Returns the object: return p1

Now when you try to access a method:

p1.sayHi(); 

Searches JavaScript sayHi i p1 First when it doesn’t find it, it checks p1.__proto__which refers to Person.prototypewhere the method is defined.

The relationship can be expressed as:

p1.__proto__ === Person.prototype; 
Person.prototype.constructor === Person; 

In summary:

How prototypes work with functions

Let’s see a complete example with functions:

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


Person.prototype.introduce = function() {
  console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old.`);
};


const person1 = new Person("Alice", 25);
const person2 = new Person("Bob", 30);

person1.introduce(); 
person2.introduce(); 


console.log(person1.__proto__ === Person.prototype); 
console.log(person2.__proto__ === Person.prototype); 
console.log(person1.__proto__ === person2.__proto__); 

The key benefit here is memory efficiency: introduce The method exists only once Person.prototypebut all instances can access it through the prototype chain.

How Prototypes Work with Classes

Introduced by ES6 class The syntax, which looks different but works the same under the hood:

class User {
  constructor(name) {
    this.name = name;
  }

  sayHi() {
    console.log(`Hi, I'm ${this.name}`);
  }
}

const user1 = new User("Charlie");
user1.sayHi(); 


console.log(typeof User); 
console.log(User.prototype); 
console.log(user1.__proto__ === User.prototype); 

Classes are basically prototypes based on JavaScript’s prototype inheritance. Internally:

  • A class is still a constructor function

  • The methods defined in the class are invoked ClassName.prototype

  • Made for example new It’s theirs __proto__ Set to the class prototype

This means that what we learned about function prototypes also applies to classes.

The result

Understanding prototypes and the prototype chain is fundamental to mastering JavaScript. These concepts form the basis of how JavaScript implements inheritance and object-oriented programming.

The key path

Let’s recap what we’ve learned:

  1. It happens in everything __proto__: This property points to the prototype from which the object inherits, enabling the prototype chain search mechanism.

  2. There are functions and classes prototype: This property serves as a blueprint for instances created with Rab new Keyword

  3. The prototype chain enables inheritance: When JavaScript cannot find a property on an object, it walks up the prototype chain until it finds or reaches the property. null.

  4. Primitive wrappers use objects: Although primitives are not objects, JavaScript temporarily wraps them in objects to provide access to methods.

  5. Class are synthetic sugars: Modern class The syntax is cleaner, but it still uses prototypes under the hood.

JavaScript may seem strange at first, but once you understand how it works under the hood, you’ll appreciate its elegant and flexible design.

Happy coding!

You may also like

Leave a Comment

At Skillainest, we believe the future belongs to those who embrace AI, upgrade their skills, and stay ahead of the curve.

Get latest news

Subscribe my Newsletter for new blog posts, tips & new photos. Let's stay updated!

@2025 Skillainest.Designed and Developed by Pro