Prototypal inheritance is about linked lookup, not copied members. The debug value is understanding method sharing, property shadowing, and prototype-chain behavior under the hood.
Explain how prototypal inheritance works in JavaScript
The Core Idea
In JavaScript, objects do not copy behavior from classes. They resolve missing properties through a prototype chain. That matters in real debugging because shared methods, shadowed properties, or unexpected lookup order all come from linked prototypes, not from duplicated members.
Every object has an internal link to another object called its prototype. If a property is missing locally, JavaScript keeps walking that chain until it finds a match or reaches null.
Concept | Description | Example / Notes |
|---|---|---|
Prototype | The object from which another object inherits properties. |
|
Prototype Chain | A chain of linked objects that JS traverses when looking up properties. | Ends when reaching |
__proto__ | A reference to an object's prototype (legacy but still widely used). | Equivalent to |
constructor.prototype | Defines the prototype for all objects created by a constructor function. | Used when creating objects via |
Example: Simple Inheritance
const animal = {
eats: true,
walk() {
console.log('Animal walks');
}
};
const dog = Object.create(animal); // dog inherits from animal
dog.barks = true;
dog.walk(); // 'Animal walks' (inherited)
console.log(dog.eats); // true
Here’s what happens when you call dog.walk():
- JS looks for
walkondog.
- It doesn’t find it, so it looks at
dog.__proto__(which points toanimal).
- Finds
walkthere and executes it.
Using constructor functions
Before ES6 classes, developers often used constructor functions to define prototypes:
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound.`);
};
const cat = new Animal('Milo');
cat.speak(); // Milo makes a sound.
All objects created using new Animal() share the same speak() method via Animal.prototype — not a copy for each instance.
ES6 class syntax
ES6 class syntax is just syntactic sugar over the same prototypal mechanism.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound.`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks.`);
}
}
const rex = new Dog('Rex');
rex.speak(); // Rex barks
Behind the scenes, Dog inherits from Animal by setting Dog.prototype.__proto__ = Animal.prototype.
Common Misunderstanding
Prototypal inheritance doesn’t copy properties — it links objects. If you change a method on the prototype, all objects linked to it see the change immediately.
animal.walk = function() { console.log('Animal strolls'); };
dog.walk(); // 'Animal strolls' (updated for all inheriting objects)
Think of it like a family tree:
- Each child (object) can use traits from their parent (prototype).
- If the child doesn’t have a skill, it checks if the parent does.
- If not, it goes further up the chain — until there’s no ancestor left.
- Every object in JS has a prototype (except
Object.prototype).
- Property lookups follow the prototype chain.
- Prototypal inheritance links objects — it doesn’t clone them.
- Modern
classsyntax still uses prototypes under the hood.
Use the relevant interview-question hub first, then move into a concrete study plan before targeted company sets.