JavaScript Interview Prep
Prototypes & Inheritance

Prototype Chain

`__proto__` vs `.prototype`

LinkedIn Hook

Ask a JavaScript developer what __proto__ and .prototype mean, 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 with new.

When you access dog.bark, JS doesn't just look at dog. It walks the __proto__ chain — all the way up to Object.prototype, and finally to null.

In this lesson you'll learn how property lookup actually works, the exact difference between __proto__ and .prototype, and why Object.getPrototypeOf is 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


Prototype Chain thumbnail


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:

ConceptWhat it isWho has it
__proto__The actual link to the parent prototype objectEvery object
.prototypeA plain object property that exists on functionsOnly 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)

Prototype Chain visual 1


Common Mistakes

  • Treating __proto__ and .prototype as interchangeable — __proto__ lives on every object and is the actual chain link, while .prototype only exists on functions and is just the template used by new.
  • Reading/writing __proto__ directly in production code — it's a legacy accessor. Use Object.getPrototypeOf() and Object.setPrototypeOf() instead.
  • Forgetting that hasOwnProperty returns false for 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. .prototype is a property that exists only on functions — it's the object that will be assigned as __proto__ to instances created via new. In short: __proto__ is the chain, .prototype is 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__ is null, 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 or null is reached (property is undefined).

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 modern Object.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 this Next: Prototypal Inheritance


This is Lesson 5.1 of the JavaScript Interview Prep Course — 14 chapters, 87 lessons.

On this page