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"); // falselegs 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 nullWhen 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
- Understanding why every array has methods like map and push without those methods being copied onto each array.
- Debugging why a method call works on an object that never explicitly defined that method.
- Reasoning about memory: shared prototype methods cost one function per class, not one per instance.
- Recognizing why own properties (like an instance field) shadow a same-named prototype method.
- Understanding how class syntax and Object.create both build on this same underlying mechanism.