Bird
Raised Fist0
Javascriptprogramming~15 mins

Prototype chain in Javascript - Deep Dive

Choose your learning style10 modes available
Overview - Prototype chain
What is it?
The prototype chain is a way JavaScript objects inherit properties and methods from other objects. When you try to access a property on an object, JavaScript looks for it on that object first. If it doesn't find it, it looks up the chain to the object's prototype, then the prototype's prototype, and so on until it finds the property or reaches the end. This chain of linked objects is called the prototype chain.
Why it matters
Without the prototype chain, JavaScript would need to copy all properties and methods to every object, wasting memory and making code harder to maintain. The prototype chain allows objects to share behavior efficiently, making JavaScript flexible and powerful. Understanding it helps you write better code and debug tricky inheritance issues.
Where it fits
Before learning the prototype chain, you should know basic JavaScript objects and properties. After this, you can learn about classes, inheritance, and advanced object-oriented patterns in JavaScript.
Mental Model
Core Idea
The prototype chain is a linked path JavaScript follows to find properties and methods an object doesn’t have itself.
Think of it like...
Imagine a family tree where you ask your parents for something you don’t have. If they don’t have it, you ask your grandparents, and so on until someone has it or you reach the oldest ancestor.
Object → Prototype → Prototype's Prototype → ... → null
  │           │                    
  └─ property? └─ property? └─ property? └─ end
Build-Up - 7 Steps
1
FoundationObjects and properties basics
🤔
Concept: Learn how objects store properties and how to access them.
In JavaScript, objects are collections of key-value pairs called properties. You can access a property using dot notation or brackets. Example: const obj = { name: 'Alice', age: 25 }; console.log(obj.name); // 'Alice' console.log(obj['age']); // 25
Result
You can get or set values inside objects using keys.
Understanding how objects hold data is the first step to seeing how inheritance works through prototypes.
2
FoundationWhat is a prototype object?
🤔
Concept: Every JavaScript object has a hidden link to another object called its prototype.
When you create an object, JavaScript sets a hidden property called [[Prototype]] that points to another object. This prototype can have properties and methods that the original object can use. Example: const parent = { greet() { return 'Hello'; } }; const child = Object.create(parent); console.log(child.greet()); // 'Hello'
Result
child can use greet() even though it’s not its own property.
Knowing that objects link to prototypes explains how properties can be shared without copying.
3
IntermediateHow property lookup works
🤔Before reading on: do you think JavaScript copies properties from the prototype to the object or just looks them up when needed? Commit to your answer.
Concept: JavaScript looks up properties along the prototype chain instead of copying them.
When you access a property, JavaScript first checks the object itself. If it’s not there, it checks the prototype, then the prototype’s prototype, and so on until it finds the property or reaches null. Example: const grandparent = { sayHi() { return 'Hi'; } }; const parent = Object.create(grandparent); const child = Object.create(parent); console.log(child.sayHi()); // 'Hi'
Result
child can use sayHi() found on grandparent via the chain.
Understanding lookup instead of copying helps explain memory efficiency and dynamic behavior.
4
IntermediateModifying prototypes affects all linked objects
🤔Before reading on: if you add a method to a prototype, do existing objects linked to it get the new method automatically? Commit to your answer.
Concept: Changing a prototype changes behavior for all objects linked to it immediately.
If you add or change a property on a prototype, all objects that inherit from it see the change right away. Example: const proto = {}; const obj1 = Object.create(proto); const obj2 = Object.create(proto); proto.sayBye = () => 'Bye'; console.log(obj1.sayBye()); // 'Bye' console.log(obj2.sayBye()); // 'Bye'
Result
Both obj1 and obj2 can use the new sayBye method.
This shows how prototypes enable shared behavior and dynamic updates across many objects.
5
IntermediatePrototype chain ends with null
🤔
Concept: The prototype chain always ends at null, which means no more objects to check.
Every prototype chain eventually reaches null, which signals the end of the chain. Example: const obj = {}; console.log(Object.getPrototypeOf(obj)); // Object.prototype console.log(Object.getPrototypeOf(Object.prototype)); // null
Result
JavaScript stops looking for properties once it reaches null.
Knowing the chain’s end prevents infinite loops and clarifies property lookup limits.
6
AdvancedUsing __proto__ and Object.getPrototypeOf
🤔Before reading on: do you think __proto__ and Object.getPrototypeOf do the same thing or different? Commit to your answer.
Concept: You can access an object's prototype using __proto__ or Object.getPrototypeOf, but one is standard and safer.
The __proto__ property is a legacy way to access an object's prototype. Object.getPrototypeOf(obj) is the standard method. Example: const obj = {}; console.log(obj.__proto__ === Object.getPrototypeOf(obj)); // true
Result
Both give the prototype, but Object.getPrototypeOf is preferred.
Understanding these access methods helps with debugging and advanced prototype manipulation.
7
ExpertPrototype chain and performance surprises
🤔Before reading on: do you think deep prototype chains slow down property access significantly? Commit to your answer.
Concept: Long prototype chains can slow property access, but JavaScript engines optimize common cases heavily.
While property lookup walks the prototype chain, modern JavaScript engines use hidden classes and inline caches to speed up access. However, very deep or dynamic prototype chains can still cause performance hits. Example: function A() {} function B() {} B.prototype = Object.create(A.prototype); function C() {} C.prototype = Object.create(B.prototype); // Deep chains like this can be slower in some cases.
Result
Property access remains fast usually, but deep chains can degrade performance.
Knowing engine optimizations and limits helps write efficient code and avoid subtle slowdowns.
Under the Hood
JavaScript objects have an internal hidden link called [[Prototype]] pointing to another object. When accessing a property, the engine first checks the object itself. If missing, it follows the [[Prototype]] link to the next object, repeating until it finds the property or reaches null. This chain lookup is done at runtime, enabling dynamic inheritance and shared behavior without copying properties.
Why designed this way?
The prototype chain was designed to allow flexible inheritance without duplicating code or data. Early JavaScript needed a lightweight way to share methods across many objects. Classical class-based inheritance was avoided to keep the language simple and dynamic. This design trades off some lookup speed for great flexibility and memory efficiency.
┌─────────┐     [[Prototype]]     ┌──────────────┐     [[Prototype]]     ┌───────────────┐
│  Object │ ───────────────────▶ │  Prototype   │ ───────────────────▶ │  Prototype's  │
│  (child)│                      │   Object     │                      │  Prototype    │
└─────────┘                      └──────────────┘                      └───────────────┘
       │                                  │                                    │
       │ property found?                   │ property found?                     │ property found?
       └─────────────Yes───────────────▶ │                                    │
                                         └─────────────Yes───────────────────▶

If no property found at any step, lookup ends at null.
Myth Busters - 4 Common Misconceptions
Quick: Does changing a property on an object’s prototype copy it to the object? Commit yes or no.
Common Belief:Changing a prototype’s property copies it to all objects linked to it.
Tap to reveal reality
Reality:Changing a prototype’s property changes it only on the prototype; objects inherit it dynamically without copying.
Why it matters:Believing in copying leads to confusion about why changes to prototypes affect all linked objects immediately.
Quick: Is the prototype chain the same as classical inheritance? Commit yes or no.
Common Belief:The prototype chain works exactly like classical class inheritance in other languages.
Tap to reveal reality
Reality:The prototype chain is a dynamic delegation system, not classical inheritance; objects inherit directly from other objects, not classes.
Why it matters:Misunderstanding this causes wrong assumptions about how inheritance and method overriding work in JavaScript.
Quick: Does every object have its own copy of inherited methods? Commit yes or no.
Common Belief:Each object has its own copy of methods inherited from its prototype.
Tap to reveal reality
Reality:Objects share methods via the prototype; methods are not copied but referenced through the chain.
Why it matters:Thinking methods are copied wastes mental effort and leads to inefficient code design.
Quick: Can the prototype chain form a loop? Commit yes or no.
Common Belief:It’s possible to create a circular prototype chain causing infinite loops.
Tap to reveal reality
Reality:JavaScript prevents circular prototype chains; the chain always ends at null.
Why it matters:Believing loops exist causes unnecessary fear of infinite loops during property lookup.
Expert Zone
1
Modifying Object.prototype affects all objects, which can cause unexpected bugs if done carelessly.
2
Shadowing a property on an object hides the prototype’s property but does not delete it from the prototype.
3
The prototype chain lookup is dynamic, so changing prototypes at runtime can alter behavior of existing objects.
When NOT to use
Avoid relying heavily on deep prototype chains for performance-critical code; prefer composition or class-based inheritance patterns. Also, do not modify built-in prototypes like Array.prototype in production code to prevent conflicts.
Production Patterns
Developers use prototype chains to implement inheritance in frameworks and libraries. For example, JavaScript classes use prototypes under the hood. Prototype chains enable method sharing in libraries like React and Node.js core modules.
Connections
Classical inheritance
Prototype chain is a form of inheritance but differs from classical class-based inheritance.
Understanding prototype chains clarifies how JavaScript’s inheritance is more flexible and dynamic than classical models.
Delegation pattern
Prototype chain is an implementation of the delegation design pattern where objects delegate behavior to linked prototypes.
Recognizing delegation helps understand how behavior sharing works without copying.
Biological evolution
Prototype chain resembles how traits pass through generations with variations and shared features.
Seeing prototype chains like evolution shows how objects inherit and override properties dynamically over time.
Common Pitfalls
#1Modifying a prototype property expecting it to copy to objects.
Wrong approach:const proto = { greet() { return 'Hi'; } }; const obj = Object.create(proto); proto.greet = () => 'Hello'; console.log(obj.greet()); // 'Hello' // But expecting obj to have its own greet method now
Correct approach:const proto = { greet() { return 'Hi'; } }; const obj = Object.create(proto); // obj.greet is still from proto, no copy made console.log(obj.greet()); // 'Hello' after proto change
Root cause:Misunderstanding that prototype properties are shared references, not copied.
#2Using __proto__ to set prototype in production code.
Wrong approach:const obj = {}; obj.__proto__ = anotherObj; // discouraged
Correct approach:const obj = Object.create(anotherObj); // standard and safer
Root cause:Not knowing __proto__ is legacy and can cause performance and compatibility issues.
#3Assuming methods are copied per object causing memory waste.
Wrong approach:function Person() { this.sayHi = function() { return 'Hi'; }; } const p1 = new Person(); const p2 = new Person();
Correct approach:function Person() {} Person.prototype.sayHi = function() { return 'Hi'; }; const p1 = new Person(); const p2 = new Person();
Root cause:Not using prototype to share methods leads to unnecessary duplication.
Key Takeaways
The prototype chain is how JavaScript objects inherit properties by linking to other objects dynamically.
Property lookup walks up the prototype chain until it finds the property or reaches the end at null.
Modifying a prototype affects all objects linked to it immediately, enabling shared behavior.
Understanding the prototype chain helps write efficient, maintainable JavaScript and debug inheritance issues.
Prototype chains differ from classical inheritance by using delegation instead of copying or classes.

Practice

(1/5)
1. What does the prototype chain in JavaScript help with?
easy
A. Sharing properties and methods between objects
B. Creating new variables automatically
C. Running code faster
D. Stopping code execution

Solution

  1. Step 1: Understand prototype chain purpose

    The prototype chain allows objects to share properties and methods by linking them.
  2. Step 2: Identify correct description

    Sharing properties and methods matches the prototype chain's role, unlike other options.
  3. Final Answer:

    Sharing properties and methods between objects -> Option A
  4. Quick Check:

    Prototype chain = Sharing properties and methods [OK]
Hint: Prototype chain shares properties/methods between objects [OK]
Common Mistakes:
  • Thinking it creates variables
  • Assuming it speeds up code
  • Believing it stops code
2. Which of the following is the correct way to create an object with a specific prototype in JavaScript?
easy
A. let obj = prototypeObj.create();
B. let obj = Object.create(prototypeObj);
C. let obj = new Object(prototypeObj);
D. let obj = Object.prototype(prototypeObj);

Solution

  1. Step 1: Recall Object.create syntax

    Object.create(prototypeObj) creates a new object with prototypeObj as its prototype.
  2. Step 2: Check other options

    Other options use incorrect syntax or methods that don't exist.
  3. Final Answer:

    let obj = Object.create(prototypeObj); -> Option B
  4. Quick Check:

    Object.create() creates object with prototype [OK]
Hint: Use Object.create(prototype) to set prototype correctly [OK]
Common Mistakes:
  • Using new Object() with prototype argument
  • Calling create() on prototype object
  • Trying to call Object.prototype as a function
3. What will be the output of this code?
const parent = { greet() { return 'Hello'; } };
const child = Object.create(parent);
console.log(child.greet());
medium
A. undefined
B. null
C. TypeError
D. 'Hello'

Solution

  1. Step 1: Understand prototype lookup

    child has no greet method, so JavaScript looks up to parent where greet exists.
  2. Step 2: Call greet method from parent

    Calling child.greet() runs parent.greet(), returning 'Hello'.
  3. Final Answer:

    'Hello' -> Option D
  4. Quick Check:

    Prototype lookup finds greet() = 'Hello' [OK]
Hint: If property missing, JS checks prototype chain [OK]
Common Mistakes:
  • Expecting undefined because child lacks greet
  • Thinking it causes error
  • Assuming null is returned
4. Find the error in this code snippet:
const animal = { eats: true };
const rabbit = Object.create(animal);
rabbit.eats = false;
console.log(rabbit.eats);
console.log(animal.eats);
medium
A. No error; output is as expected
B. Object.create should not be used here
C. rabbit.eats does not override animal.eats
D. animal.eats is changed to false

Solution

  1. Step 1: Understand property shadowing

    Setting rabbit.eats creates a new property on rabbit, shadowing animal.eats.
  2. Step 2: Check outputs

    rabbit.eats logs false; animal.eats remains true. This is expected behavior.
  3. Final Answer:

    No error; output is as expected -> Option A
  4. Quick Check:

    Property shadowing works correctly [OK]
Hint: Setting property on child shadows parent's property [OK]
Common Mistakes:
  • Thinking parent's property changes
  • Believing Object.create is wrong here
  • Expecting error from property override
5. You want to create a chain where child inherits from parent, and parent inherits from grandparent. Which code correctly sets this prototype chain?
hard
A. const grandparent = {}; const parent = Object.create(child); const child = Object.create(parent);
B. const grandparent = {}; const parent = {}; const child = Object.create(parent); child.__proto__ = grandparent;
C. const grandparent = {}; const parent = Object.create(grandparent); const child = Object.create(parent);
D. const grandparent = {}; const parent = Object.create(grandparent); const child = Object.create(grandparent);

Solution

  1. Step 1: Set parent prototype to grandparent

    Using Object.create(grandparent) for parent sets grandparent as prototype.
  2. Step 2: Set child prototype to parent

    Using Object.create(parent) for child sets parent as prototype, completing chain.
  3. Step 3: Check other options

    B incorrectly overrides child's prototype to grandparent using __proto__, skipping parent; C creates a circular reference (child not defined when creating parent); D sets child directly to grandparent, skipping parent.
  4. Final Answer:

    const grandparent = {}; const parent = Object.create(grandparent); const child = Object.create(parent); -> Option C
  5. Quick Check:

    Prototype chain: child -> parent -> grandparent [OK]
Hint: Use Object.create in order from top to bottom [OK]
Common Mistakes:
  • Setting child prototype to grandparent directly
  • Reversing prototype chain order
  • Using __proto__ instead of Object.create
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard