Understanding __proto__ vs prototype in JavaScript

April 27, 2025
~4 min read
JavaScriptOOPPrototypes

Introduction

JavaScript's prototype system is one of its most powerful features, but it can be confusing to understand the difference between __proto__ and prototype. In this post, we'll explore both concepts with clear examples and deep insights into how they work.

What is a Prototype?

A prototype in JavaScript is a mechanism that allows objects to inherit properties and methods from other objects. Think of it as a template or a blueprint that other objects can use to share common functionality.
In JavaScript, every object has a prototype, which is another object that it inherits from. This creates a chain of inheritance, known as the prototype chain.

The Basics

Let's start with the fundamental concepts:
  • prototype is a property of constructor functions. It defines the properties and methods that will be shared by all instances of the constructor.
  • __proto__ is a property of objects that points to their prototype. It is the actual link between objects in the prototype chain.
According to the ECMAScript specification, every object in JavaScript has an internal `[[Prototype]]` property, which is exposed to user-level code via the `__proto__` property. This is what makes JavaScript's prototype-based inheritance possible.

Simple Example

Let's look at a simple example to understand the relationship:
javascript
1// Constructor function
2    function Person(name) {
3      this.name = name;
4    }
5
6    // Adding a method to the prototype
7    Person.prototype.sayHello = function() {
8      console.log(`Hello, I'm ${this.name}`);
9    };
10
11    // Creating an instance
12    const person = new Person('John');
13
14    // The relationship between __proto__ and prototype
15    console.log(person.__proto__ === Person.prototype); // true
16    console.log(person.sayHello()); // "Hello, I'm John"

Understanding the Chain

When you try to access a property on an object, JavaScript follows this process:
  1. Check if the property exists on the object itself
  2. If not, check the object's __proto__ (which points to the constructor's prototype)
  3. Continue up the prototype chain until the property is found or the chain ends
This mechanism is known as dynamic dispatch or delegation. Unlike static dispatch (where references are resolved at compile time), dynamic dispatch resolves references at runtime, allowing for full mutability of the inheritance chain.

Complex Example

Let's explore a more complex example with inheritance:
javascript
1// Base class
2    function Animal(name) {
3      this.name = name;
4    }
5
6    Animal.prototype.makeSound = function() {
7      console.log('Some generic sound');
8    };
9
10    // Derived class
11    function Dog(name, breed) {
12      // Call the Animal constructor to initialize 'name' in the Dog instance
13      Animal.call(this, name); // <-- This ensures Dog instances get the 'name' property from Animal
14      this.breed = breed;
15    }
16
17    // Set up inheritance
18    Dog.prototype = Object.create(Animal.prototype);
19    Dog.prototype.constructor = Dog;
20
21    // Add Dog-specific method
22    Dog.prototype.bark = function() {
23      console.log('Woof!');
24    };
25
26    // Create instances
27    const dog = new Dog('Rex', 'German Shepherd');
28
29    // The prototype chain
30    console.log(dog.__proto__ === Dog.prototype); // true
31    console.log(dog.__proto__.__proto__ === Animal.prototype); // true
32    console.log(dog.__proto__.__proto__.__proto__ === Object.prototype); // true
33
34    // Method calls
35    dog.makeSound(); // "Some generic sound"
36    dog.bark(); // "Woof!"
Note on Object.create:
Object.create(proto) creates a new object and sets its prototype to proto. This is the recommended way to set up inheritance in JavaScript, as it cleanly establishes the prototype chain without invoking the constructor of the parent. In the example above, Dog.prototype = Object.create(Animal.prototype) means all Dog instances inherit from Animal, but the Animal constructor is not called when setting up the prototype.

Key Differences

Aspectprototype__proto__
What is it?A property of constructor functionsA property of all objects (instances)
PurposeDefines properties/methods shared by all instancesPoints to the object's prototype (the actual link in the chain)
Where is it found?On constructor functions (e.g., Person.prototype)On all objects (e.g., person.__proto__)
How is it used?To add shared methods/properties for instancesTo traverse the prototype chain for inheritance
Best PracticeUse to define shared behaviorAvoid direct manipulation; use Object.getPrototypeOf/setPrototypeOf

Best Practices

  • Use Object.create() for setting up inheritance
  • Avoid modifying __proto__ directly
  • Use Object.getPrototypeOf() instead of __proto__ when possible
  • Remember to set the constructor property when creating custom prototype chains
  • Use Object.setPrototypeOf() for changing prototypes after object creation

Class-based Inheritance

It's important to note that class-based inheritance in JavaScript is implemented on top of the prototype-based delegation. When you use the class keyword, it's essentially syntactic sugar that:
  • Creates a constructor function
  • Sets up the prototype chain
  • Handles method inheritance
  • Manages the super keyword

Conclusion

Understanding the difference between __proto__ and prototype is crucial for working with JavaScript's object-oriented features. While __proto__ represents the actual prototype chain link, prototype is used to define shared properties and methods for all instances of a constructor function. This prototype-based inheritance system is what makes JavaScript so flexible and powerful.

References