← All concepts
Object-Oriented Programming

Prototypes and Inheritance

When an object does not have a property itself, JavaScript looks for it on the object's prototype instead.

Loading visual…

Definition

Every JavaScript object has an internal link to another object called its prototype, accessible through `Object.getPrototypeOf(obj)` or the legacy `__proto__` accessor. When you read a property, the engine first checks the object's own properties. If the property is not there, it does not give up, it follows the prototype link and checks that object's own properties, then that object's prototype, and so on. This sequence of linked objects is the prototype chain, and it ends at `Object.prototype`, whose own prototype is `null`. If the chain runs out with no match, the read returns `undefined` instead of throwing. This is how methods are shared without copying them onto every object. A constructor function's methods usually live on `Constructor.prototype`, one shared object, and every instance created with `new Constructor()` gets its `[[Prototype]]` set to that same object. So `instance.method()` works even though `method` is never an own property of `instance`, the lookup walks up to the prototype and finds it there. Own properties always win over inherited ones: if an instance defines its own version of a name, the chain walk stops at the instance and the prototype's version is never reached.

Examples

function Dog(name) {
  this.name = name;
}
Dog.prototype.speak = function () {
  return this.name + " barks";
};
const rex = new Dog("Rex");
rex.speak(); // "Rex barks"

rex has no own speak property, so the lookup walks up rex's prototype link to Dog.prototype, finds speak there, and calls it with this bound to rex.

const rex = { name: "Rex" };
const animal = { legs: 4 };
Object.setPrototypeOf(rex, animal);
rex.legs; // 4, found on the prototype
rex.hasOwnProperty("legs"); // false

legs is not an own property of rex, but the prototype chain reaches animal and finds it there, while hasOwnProperty correctly reports that rex itself never had it.

function Base() {}
Base.prototype.greet = () => "hi";
const obj = {};
Object.setPrototypeOf(obj, Base.prototype);
obj.missing; // undefined, chain reaches Object.prototype then null

When no object in the chain has the property, the walk reaches Object.prototype, then its prototype null, and the read quietly returns undefined.

Where you see this

Practice this

Further reading