Prototype Chain
`__proto__` vs `.prototype`
LinkedIn Hook
Ask a JavaScript developer what
__proto__and.prototypemean, and most of them will freeze.They look almost identical. They both pop up in every inheritance diagram. But they are NOT the same thing — and confusing them is why so many devs never truly understand how inheritance works in JS.
Here's the truth: every object in JavaScript has a hidden link called
[[Prototype]], exposed as__proto__. That link is the real prototype chain..prototype, on the other hand, is just a plain property that lives on functions — it becomes__proto__of instances created withnew.When you access
dog.bark, JS doesn't just look atdog. It walks the__proto__chain — all the way up toObject.prototype, and finally tonull.In this lesson you'll learn how property lookup actually works, the exact difference between
__proto__and.prototype, and whyObject.getPrototypeOfis the modern way to read the chain.Master this one concept, and the rest of JavaScript inheritance will finally click.
Read the full lesson -> [link]
#JavaScript #InterviewPrep #Prototypes #JSEngine #Frontend #CodingInterview #WebDevelopment
What You'll Learn
- What the
[[Prototype]]internal link is and how every object uses it - The exact difference between
__proto__(the link) and.prototype(the blueprint) - How JavaScript performs property lookup by walking the chain up to
null
The Prototype Chain — A Family Tree
Think of the prototype chain like a family tree. When someone asks you "do you know how to cook biryani?", you first check if you know. If not, you ask your mom. If she doesn't know, she asks your grandma. This chain of "asking the parent" continues until you either find someone who knows, or you hit the end of the line (null — no more ancestors to ask).
Every object in JavaScript has a hidden internal link called [[Prototype]]. This link points to another object — its prototype. When you try to access a property that doesn't exist on the object itself, JavaScript follows this [[Prototype]] link and looks in the prototype. If it's not there either, it follows that prototype's [[Prototype]] link, and so on — all the way up until it reaches null.
The Two Things People Confuse
There are two separate concepts that sound almost identical but are completely different:
| Concept | What it is | Who has it |
|---|---|---|
__proto__ | The actual link to the parent prototype object | Every object |
.prototype | A plain object property that exists on functions | Only functions |
Key insight: __proto__ IS the prototype chain. .prototype is just a storage location — it's the object that will become __proto__ of instances created by that function with new.
Seeing the Chain in Action
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
return "Hi, I'm " + this.name;
};
const rakibul = new Person("Rakibul");
// The chain:
console.log(rakibul.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true
// So the full chain is:
// rakibul -> Person.prototype -> Object.prototype -> null
Property Lookup — How JS Walks the Chain
function Animal(type) {
this.type = type;
}
Animal.prototype.breathe = function () {
return this.type + " is breathing";
};
const cat = new Animal("Cat");
// 1. JS looks for 'type' on cat — found! Returns "Cat"
console.log(cat.type); // "Cat"
// 2. JS looks for 'breathe' on cat — not found.
// Walks up to Animal.prototype — found! Returns function.
console.log(cat.breathe()); // "Cat is breathing"
// 3. JS looks for 'toString' on cat — not found.
// Walks up to Animal.prototype — not found.
// Walks up to Object.prototype — found!
console.log(cat.toString()); // "[object Object]"
// 4. JS looks for 'fly' on cat — not found.
// Walks up to Animal.prototype — not found.
// Walks up to Object.prototype — not found.
// Reaches null — returns undefined.
console.log(cat.fly); // undefined
__proto__ vs .prototype — The Diagram
// Let's trace everything:
function Foo() {}
// Foo is a function, so it has .prototype
console.log(typeof Foo.prototype); // "object"
// Foo.prototype has a constructor pointing back to Foo
console.log(Foo.prototype.constructor === Foo); // true
// When we create an instance:
const f = new Foo();
// The instance's __proto__ IS Foo.prototype (same reference)
console.log(f.__proto__ === Foo.prototype); // true
// Foo itself is an object too — its __proto__ is Function.prototype
console.log(Foo.__proto__ === Function.prototype); // true
// And Function.prototype's __proto__ is Object.prototype
console.log(Function.prototype.__proto__ === Object.prototype); // true
// The chain ends:
console.log(Object.prototype.__proto__); // null
Object.getPrototypeOf — The Modern Way
__proto__ is technically a legacy getter/setter. The proper way to access the prototype chain is:
const arr = [1, 2, 3];
// Preferred:
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true
// Set prototype (rarely needed):
const parent = { greet() { return "hello"; } };
const child = {};
Object.setPrototypeOf(child, parent);
console.log(child.greet()); // "hello"
// Check own property vs inherited:
const obj = { a: 1 };
console.log(obj.hasOwnProperty("a")); // true
console.log(obj.hasOwnProperty("toString")); // false (inherited)
Common Mistakes
- Treating
__proto__and.prototypeas interchangeable —__proto__lives on every object and is the actual chain link, while.prototypeonly exists on functions and is just the template used bynew. - Reading/writing
__proto__directly in production code — it's a legacy accessor. UseObject.getPrototypeOf()andObject.setPrototypeOf()instead. - Forgetting that
hasOwnPropertyreturnsfalsefor inherited properties — if you loop or check properties, you may accidentally include prototype methods unless you filter them out.
Interview Questions
Q: What is the difference between __proto__ and .prototype?
__proto__is the actual internal prototype link that every object has — it points to the object's prototype and is used for property lookup..prototypeis a property that exists only on functions — it's the object that will be assigned as__proto__to instances created vianew. In short:__proto__is the chain,.prototypeis the blueprint for the chain.
Q: What is at the top of every prototype chain?
Object.prototype. It sits at the top of every prototype chain, and its own__proto__isnull, which terminates the chain.
Q: How does property lookup work in JavaScript?
When you access a property, JS first looks at the object itself. If not found, it follows
__proto__to the prototype and looks there. This continues up the chain until the property is found ornullis reached (property isundefined).
Q: What is [[Prototype]]?
[[Prototype]]is the internal slot every JavaScript object has that points to its prototype object. It's exposed through the legacy__proto__accessor and the modernObject.getPrototypeOf()/Object.setPrototypeOf()APIs. It is the actual link that forms the prototype chain.
Q: What does Object.getPrototypeOf() do?
It returns the value of an object's internal
[[Prototype]]slot — that is, the object it inherits from. It's the standards-compliant replacement for reading__proto__directly.
Quick Reference — Cheat Sheet
PROTOTYPE CHAIN — QUICK MAP
Every object has __proto__ -> the chain link
Only functions have .prototype -> the blueprint for `new`
Chain example (rex is a Dog):
rex
^ __proto__
Dog.prototype { bark: fn }
^ __proto__
Animal.prototype { eat: fn }
^ __proto__
Object.prototype { toString, hasOwnProperty, valueOf, ... }
^ __proto__
null
__proto__:
- Every object has it
- IS the prototype chain link
- Points to the object it inherits from
- Prefer Object.getPrototypeOf()
.prototype:
- Only functions have it
- A plain object property
- Becomes __proto__ of instances made with `new`
- Has .constructor pointing back to the function
Property lookup:
obj -> obj.__proto__ -> ... -> Object.prototype -> null
First match wins. Miss -> undefined.
Previous: Binding Priority & Lost
thisNext: Prototypal Inheritance
This is Lesson 5.1 of the JavaScript Interview Prep Course — 14 chapters, 87 lessons.