Skip to content
Intermediate10 min study

Prototype chain

Trace property lookup, inheritance, classes, own properties, and shared behavior through JavaScript's prototype chain.

Question progress0 / 10 completed
Start the lesson
Prototype chain visual explanation

WHAT YOU WILL BE ABLE TO DO

Learning outcomes

  • Explain prototype chain in plain language.
  • Connect the behavior to the underlying browser or framework model.
  • Implement the core pattern and reason through edge cases.
  • Answer common follow-ups without relying on memorized phrases.

01Overview

Every object has an internal [[Prototype]] link (accessible via Object.getPrototypeOf or the non-standard __proto__). Property lookups that miss on the object itself walk up this chain until they hit Object.prototype or null.

02Mental model

This is delegation, not copying — instances share behavior through the chain instead of duplicating methods. class/extends syntax builds and wires this same prototype chain automatically; it doesn't introduce a separate inheritance model.

Think of it like this: asking your immediate family for something first, and only going to your grandparents if nobody closer has it — the lookup stops the moment it finds an answer at any level.

03Examples

JavaScript
const animal = { speak() { return 'generic sound'; } };const dog = Object.create(animal);dog.speak(); // 'generic sound' — found via the prototype chaindog.hasOwnProperty('speak'); // false — it's inherited, not own

04Check understanding

What does hasOwnProperty tell you that a plain property check doesn't?

obj.prop can return an inherited value; hasOwnProperty confirms the property exists directly on the object, not somewhere up the prototype chain.

How to say it out loud: "Every object in JavaScript has an internal link to another object called its prototype, and when you look up a property that isn't on the object itself, the engine walks up that chain — checking the prototype, then the prototype's prototype, and so on — until it finds the property or hits null. This is delegation, not copying: instances share behavior through that chain instead of each one having its own copy of every method. Class syntax with extends is really just a cleaner way of wiring up the exact same prototype chain — it doesn't introduce a separate inheritance mechanism underneath."

DDConcept deep dives

Deep dive 1

Property lookup follows internal prototype links

Reading a property first checks the receiver's own property descriptor. If absent, lookup follows [[Prototype]] repeatedly until it finds a descriptor or reaches null. If the descriptor is a getter, the getter executes with the original receiver as this, which lets inherited accessors operate on instance data.

  • Object.hasOwn distinguishes direct data from inherited data.
  • The in operator reports both own and inherited properties.
  • Shadowing creates an own property with the same name; it does not alter the prototype property.

Deep dive 2

new connects instances to constructor prototypes

A new call creates an object whose prototype normally points at Constructor.prototype, binds this to it, executes the constructor, and returns the created object unless the constructor explicitly returns another object. Methods placed on the prototype are shared; methods created inside the constructor are allocated per instance.

  • Constructor.prototype is a property on the function, not the function's own [[Prototype]].
  • class syntax defines prototype methods and clearer inheritance rules over the same object model.
  • Object.create lets code choose a prototype without running a constructor.

Deep dive 3

Prototype mutation crosses trust boundaries

Changing a widely shared prototype affects every object that inherits from it. Unsafe recursive merges can allow keys such as __proto__ or constructor.prototype to write attacker-controlled values into a shared prototype. Code that trusts inherited configuration or authorization flags can then behave incorrectly.

  • Validate structured input and allowlist expected keys at the boundary.
  • Use Object.hasOwn for security-sensitive records.
  • Null-prototype objects can be useful dictionaries but still require schema validation.

QAInterview questions and model answers

Attempt each answer aloud before opening it. The model answer shows the depth and precision expected in an interview; it is not a script to memorize.

Intermediate · Coding · 1 min · Question 1How does property lookup use the prototype chain?Open model answer

Model answer

The engine first checks the object's own properties. If absent, it follows the object's internal [[Prototype]] link and repeats until it finds a property or reaches null. Accessor properties may execute a getter with the original receiver as this.

JavaScript
const animal = { speak() { return 'generic'; } };const dog = Object.create(animal);dog.bark = () => 'woof';
dog.bark();  // 'woof'    — own propertydog.speak(); // 'generic' — found one level up on `animal`dog.fly;     // undefined — chain ends at Object.prototype -> null
Open question page →
Intermediate · Coding · 1 min · Question 2How are constructor.prototype and an instance's prototype related?Open model answer

Model answer

When a constructable function is called with new, the new object's [[Prototype]] is normally set to the constructor's prototype property. The prototype property itself is just an ordinary property on the constructor function; it is not the constructor's own prototype.

JavaScript
function Point(x) { this.x = x; }Point.prototype.describe = function () { return `x=${this.x}`; };
const p = new Point(3);Object.getPrototypeOf(p) === Point.prototype; // truep.describe();                                 // "x=3" (via the chain)
Open question page →
Intermediate · Conceptual · 1 min · Question 3What does the class syntax change?Open model answer

Model answer

Classes provide clearer syntax and semantics over prototype-based behavior: methods live on the prototype, constructors initialize instances, and extends links both constructor and prototype chains. Classes are strict, cannot be called without new, and support private fields.

Open question page →
Intermediate · Coding · 1 min · Question 4What is the difference between own and inherited properties?Open model answer

Model answer

Own properties are directly stored on the object and can be checked with Object.hasOwn. The in operator also considers the prototype chain. Object.keys enumerates own enumerable string-keyed properties only.

JavaScript
const base = { inherited: 1 };const obj = Object.create(base);obj.own = 2;
'inherited' in obj;            // true  — walks the chainObject.hasOwn(obj, 'inherited'); // false — only this objectObject.keys(obj);              // ['own']
Open question page →
Intermediate · Conceptual · 1 min · Question 5Why is mutating built-in prototypes risky?Open model answer

Model answer

It changes behavior globally, can collide with future platform additions, affects unrelated code, and complicates enumeration and security assumptions. Use standalone utilities, composition, or carefully scoped polyfills that follow standards.

Open question page →
Advanced · Coding · 1 min · Question 6What is prototype pollution?Open model answer

Model answer

It is modification of a shared prototype through unsafe handling of keys such as __proto__, constructor, or prototype. Inherited attacker-controlled values can alter authorization or configuration logic. Validate keys, use safe merge utilities, and prefer null-prototype dictionaries where appropriate.

JavaScript
// Unsafe deep-merge lets a payload reach Object.prototype:merge({}, JSON.parse('{"__proto__": {"isAdmin": true}}'));({}).isAdmin; // true — every plain object is now affected
// Safer: reject dangerous keys, or use Object.create(null) dictionaries.
Open question page →
Intermediate · Conceptual · 1 min · Question 7How does instanceof work?Open model answer

Model answer

It generally checks whether the constructor's prototype object appears in the candidate object's prototype chain, with Symbol.hasInstance allowing customized behavior.

Open question page →
Advanced · Conceptual · 1 min · Question 8What does Object.setPrototypeOf cost?Open model answer

Model answer

Changing an existing object's prototype can invalidate engine optimizations and affect later property lookup. Create objects with the desired prototype instead of mutating hot objects.

Open question page →
Intermediate · Conceptual · 1 min · Question 9What is a property descriptor?Open model answer

Model answer

It defines a property's value and writability or getter and setter, plus enumerability and configurability. Assignment behavior depends on descriptors found across the chain.

Open question page →
Beginner · Conceptual · 1 min · Question 10Why can for...in be dangerous for record iteration?Open model answer

Model answer

It enumerates enumerable string properties from both the object and its prototypes. Object.keys or Object.entries better expresses own-property record iteration.

Open question page →

SCScenario questions

Scenario 1

A configuration merge accepts JSON input and unrelated objects later gain an isAdmin property. What happened?

  1. Inspect recursive merge handling of special property names.
  2. Check both own properties and inherited values.
  3. Reproduce with a minimal payload.
  4. Block dangerous paths and replace the unsafe merge implementation.
Reveal worked answer

This suggests prototype pollution. A recursive merge likely traversed __proto__ or constructor.prototype and wrote to Object.prototype. I would patch the merge boundary, allowlist expected schema keys, use Object.hasOwn when consuming security-sensitive data, upgrade the affected dependency, and assess whether polluted state crossed a trust boundary.

Verify and go deeper