How does prototypal inheritance work?
By FrontendPro Editorial Team Updated 9/26/2026
Answer
Every JavaScript object holds a hidden link to another object, its prototype. When you read a property that the object does not have, the engine follows that link and looks there instead, then at that object's prototype, and so on. This chain ends at null. If the property is not found anywhere along the way, you get undefined.
So inheritance here is not copying — it is delegation at lookup time. Add a method to a prototype after instances already exist and they all gain it immediately.
const animal = {
describe() {
return `${this.name} makes a sound`;
},
};
const dog = Object.create(animal);
dog.name = "Bolt";
dog.describe(); // "Bolt makes a sound" — found on animal
Object.getPrototypeOf(dog); // animal
Note this inside describe is dog, not animal. The method is found on the prototype but runs against the object you called it on.
How classes fit in
class is syntax over this same mechanism, not a different model:
class Animal {
constructor(name) { this.name = name; }
describe() { return `${this.name} makes a sound`; }
}
class Dog extends Animal {
bark() { return "Woof"; }
}
const bolt = new Dog("Bolt");
// bolt -> Dog.prototype -> Animal.prototype -> Object.prototype -> null
Methods live on Dog.prototype and Animal.prototype; bolt itself only stores name. That is why every instance shares one copy of each method.
Practical notes
- Prefer
Object.getPrototypeOf()over the legacy__proto__. - Changing an object's prototype after creation with
Object.setPrototypeOf()is slow; set it at creation instead. - Shadowing works as expected: assigning
dog.describe = ...puts the property ondogand hides the prototype's version without modifying it.
