JavaScript uses prototypal inheritance, not classical inheritance. Every object has an internal [[Prototype]] link to another object.
Think of prototypes like looking up a word in a family of dictionaries. You first check your own dictionary (the object itself). If the word isn't there, you check your parent's dictionary. Then your grandparent's. You keep going up the chain until you find the definition — or run out of dictionaries. This is exactly how property lookup works in JavaScript.
Understanding this chain — and the difference between __proto__ and prototype — is the key to understanding how properties are looked up, how new works, and what class actually does.
Prerequisites: JS Foundations #3 — Closures
1. __proto__ vs prototype — The Most Confused Concept
There are two different things that sound similar:
__proto__(or[[Prototype]]): exists on every object — it's the link to the object it inherits fromprototype: exists only on functions — it's the object that becomes the__proto__of instances created bynew
Loading editor...
The mental model:
naveen ──.__proto__──→ Person.prototype ──.__proto__──→ Object.prototype ──.__proto__──→ null
{ name: "Naveen" } { greet: fn } { hasOwnProperty, toString, ... }
2. The Prototype Chain — How Property Lookup Works
When you access obj.prop, the engine:
- Looks on
objitself - If not found, looks on
obj.__proto__ - If not found, looks on
obj.__proto__.__proto__ - Continues until it reaches
null— then returnsundefined
Loading editor...
3. Setting Properties on the Prototype
Properties on the prototype are shared across all instances. Mutating a reference type on the prototype affects everyone:
Loading editor...
4. What new Actually Does (Step by Step)
Loading editor...
5. Constructor Property
Every prototype object has a .constructor property pointing back to the function:
Loading editor...
This is easily broken if you overwrite prototype entirely:
Loading editor...
6. Inheritance Without Classes
Before class extends, we built inheritance chains manually:
Loading editor...
The prototype chain we built:
rex ──→ Dog.prototype ──→ Animal.prototype ──→ Object.prototype ──→ null
7. Object.create() — The Purest Form of Prototypal Inheritance
You can create an object that inherits from another without any constructor function:
Loading editor...
8. instanceof — Checking the Prototype Chain
obj instanceof Constructor walks obj.__proto__ up the chain and checks if it ever equals Constructor.prototype:
Loading editor...
9. for...in vs hasOwnProperty — Why It Matters
for...in loops over all enumerable properties, including inherited ones. Use hasOwnProperty to filter them out:
Loading editor...
Always guard for...in with hasOwnProperty unless you specifically want inherited properties.
10. Object.create(null) — An Object with No Prototype
Sometimes you want a plain dictionary without any inherited baggage (no toString, hasOwnProperty, etc.):
Loading editor...
This is useful for lookup maps where keys might collide with built-in method names (like toString, constructor, __proto__).
11. class — Syntax Sugar Over Prototypes
Modern class syntax does the same thing under the hood:
Loading editor...
Key Takeaways
| Concept | Meaning |
|---|---|
__proto__ / [[Prototype]] | The link from an object to its parent — exists on EVERY object |
prototype | The object that becomes __proto__ for new instances — exists only on FUNCTIONS |
new | Creates object, links __proto__, calls constructor, returns object |
Object.create(proto) | Pure prototypal inheritance — no constructor needed |
instanceof | Walks __proto__ chain checking against Constructor.prototype |
class extends | Syntax sugar — builds the same __proto__ chain underneath |
- Properties are looked up by walking the
__proto__chain until found ornull. - Don't put mutable reference types (arrays, objects) on
prototype— they are shared. Object.create(null)creates an object with no prototype — useful for dictionaries.
Next: JS Foundations #5 — Equality & Type Coercion — == vs ===, the abstract equality algorithm, and why [] == ![] is true.
