Why Objects Share Behavior: The Story of prototype and __proto__ in JavaScript
In JavaScript, prototype is a property of functions used to define shared behavior for instances, while __proto__ is a property of objects that links them to that prototype, forming the prototype chain used for property lookup.
At some point, you create multiple objectsâŚ
and they all seem to âshareâ the same behavior.
You didnât copy methods into each one.
You didnât manually connect them.
Yet somehow, they all know what to do.
Thatâs not magic.
Itâs the prototype system working behind the scenes.
Two Sides of the Same System
To understand this, you need to look at it from two perspectives.
On one side, thereâs the function.
On the other, the object created from it.
JavaScript uses two different properties to connect these worlds:
prototype__proto__
They are related.
But they play completely different roles.
The Function Side: prototype
Every function in JavaScript has a property called prototype.
function Person() {}
Person.prototype.sayHi = function () {
console.log("Hi")
}This prototype is just an object.
But it has a special purpose.
It acts as a shared storage for all instances created from that function.
Instead of copying sayHi into every object, JavaScript keeps it in one place.
The Object Side: __proto__
Now when you create an object:
const p = new Person()JavaScript automatically links that object to the functionâs prototype.
Internally, it does something like this:
p.__proto__ = Person.prototypeThis is the connection.
The object doesnât own the method.
It knows where to look for it.
How Property Lookup Actually Works
When you call:
p.sayHi()JavaScript follows a process:
- check if
phassayHi - if not, look at
p.__proto__ - if still not found, continue up the chain
This is called the prototype chain.
p â Person.prototype â Object.prototype â nullThe method is found not because it exists on pâŚ
but because p knows where to search.
The Real Difference
At this point, the distinction becomes clearer.
prototypebelongs to the function__proto__belongs to the object
And more importantly:
prototypedefines shared behavior__proto__enables access to that behavior
One stores.
One links.
What Happens When You Change __proto__
Now imagine this:
p.__proto__ = {}You didnât delete anything.
Person.prototype still has sayHi.
But now the object is no longer connected to it.
So when you call:
p.sayHi()JavaScript looks:
- inside
pâ not found - inside
{}â not found
And stops.
The method is still there.
But the path to it is gone.
Why Directly Using __proto__ Is Discouraged
Even though it works, using __proto__ directly is not recommended.
There are a few reasons.
First, itâs not the real mechanism.
Itâs just a getter and setter for an internal concept called [[Prototype]].
Second, changing it dynamically can hurt performance.
JavaScript engines optimize objects based on stable structure.
Altering the prototype at runtime forces the engine to re-evaluate those optimizations.
And finally, it makes code harder to reason about.
Youâre changing how objects inherit behavior after theyâve already been created.
That can quickly become confusing.
The Better Way
Instead of modifying the prototype chain later, itâs better to define it clearly from the beginning.
You can use:
Object.create(proto)or:
Object.getPrototypeOf(obj)
Object.setPrototypeOf(obj, proto)These are more explicit and safer.
A Different Way to Think About It
Instead of seeing objects as containers of methodsâŚ
itâs more accurate to see them as:
objects + a link to shared behavior
They donât carry everything themselves.
They know where to look.
A Final Thought
prototype and __proto__ are not competing concepts.
They are two parts of the same system.
One defines what can be shared.
The other defines how it is accessed.
And once you see that connectionâŚ
JavaScriptâs inheritance model stops feeling strange.
Because itâs not copying behavior.
Itâs linking to it.