Prototype Chain in JavaScript: Complete Guide
Every JavaScript object links to another object through its prototype. Learn how the prototype chain works, how property lookup walks it, and why it powers JavaScript inheritance.
The prototype chain is the mechanism JavaScript uses to share properties and methods between objects. Every object has an internal link that points to another object. When you read a property, JavaScript checks the object itself first, then follows that link to the next object if needed, and keeps going until it finds the property or the chain reaches null.
const parent = { shared: "I am inherited" };
const child = Object.create(parent);
child.own = "I belong to child";
console.log(child.own); // "I belong to child", found on child
console.log(child.shared); // "I am inherited", found on parent
console.log(child.missing); // undefined, not found anywhereChild only has one own property: own. The shared property lives on parent, but child can still reach it through the prototype chain. When a property is nowhere in the chain, JavaScript returns undefined rather than throwing.
The Chain in Diagrams
Every plain object created with curly braces has Object.prototype as its prototype. That object provides methods like toString and hasOwnProperty that every plain object inherits, and the chain stops at null because Object.prototype itself has no prototype.
How Property Lookup Works
When you write obj.someProperty, the engine looks for it on obj first. If it is missing there, it follows the internal link to the next object and repeats the search, all the way until it finds the property or reaches null.
const grandparent = { a: 1 };
const parent = Object.create(grandparent);
parent.b = 2;
const child = Object.create(parent);
child.c = 3;
console.log(child.c); // 3, found on child itself
console.log(child.b); // 2, found on parent
console.log(child.a); // 1, found on grandparent
console.log(child.z); // undefined, reached nullThis is a linked-list walk, not a copy. A child cannot delete or modify a property that lives higher up the chain, though it can shadow that property by creating its own with the same name.
Property Shadowing
If an object has a property with the same name as one on its prototype, the own property wins. This is called shadowing.
const proto = { value: "from prototype" };
const obj = Object.create(proto);
obj.value = "from object";
console.log(obj.value); // "from object", own property winsSetting obj.value creates a new own property; it never modifies the prototype's version, which is still there just hidden behind the closer match. Shadowing is how method overriding works: a child object can define its own version of a method that takes precedence over the parent's.
const animal = {
speak() { return "Some generic sound"; }
};
const dog = Object.create(animal);
dog.speak = function () { return "Woof!"; };
console.log(dog.speak()); // "Woof!"Built-in Prototype Chains
Every built-in type has its own prototype chain. Arrays, functions, and dates all get their methods this way rather than storing a copy on each value.
const arr = [1, 2, 3];
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true
function fn() {}
console.log(Object.getPrototypeOf(fn) === Function.prototype); // true
const d = new Date();
console.log(Object.getPrototypeOf(d) === Date.prototype); // trueArray.prototype contains methods like map, filter, and push. Function.prototype contains call, bind, and apply. Every one of these chains eventually leads to Object.prototype and then null.
Changing the Prototype
The clean way to set an object's prototype is Object.create(), since it wires up the link at the moment the object is made.
const parent = { color: "blue" };
const child = Object.create(parent);
child.size = "large";
console.log(Object.getPrototypeOf(child) === parent); // trueYou can also use the proto key inside an object literal, which is standardized for exactly this purpose and reads a bit more naturally in some code.
const child2 = { __proto__: { color: "blue" }, size: "large" };
console.log(child2.color); // "blue"Object.setPrototypeOf() can change an existing object's prototype, but avoid it when possible. Changing the prototype after creation disrupts engine optimizations and can make property access noticeably slower. Set the prototype at creation time with Object.create() or the proto literal key instead.
Checking Own vs Inherited Properties
Since the prototype chain makes inherited properties look like own properties at first glance, you sometimes need to check where a property actually lives.
const parent = { inherited: true };
const child = Object.create(parent);
child.own = true;
console.log(child.hasOwnProperty("own")); // true
console.log(child.hasOwnProperty("inherited")); // false
console.log("inherited" in child); // true| Check | Looks at own properties only? | Looks at the whole chain? |
|---|---|---|
hasOwnProperty() | Yes | No |
in operator | No | Yes |
Use hasOwnProperty(), or the newer Object.hasOwn(), whenever you need to distinguish an object's own properties from properties it only inherits.
Object.create(null): No Prototype
You can create an object with no prototype at all, which is useful for a pure dictionary that should never collide with inherited keys.
const dict = Object.create(null);
dict.hello = "world";
console.log(dict.hello); // "world"
console.log(dict.toString); // undefined, no Object.prototype at allObjects like this lack every Object.prototype method, so use Object.hasOwn(dict, "hello") instead of dict.hasOwnProperty("hello"), since the latter does not exist on a null-prototype object.
The Prototype Chain in Practice
Here is a concrete example showing how the chain lets you build a simple inheritance model out of plain objects, without any class syntax at all.
const vehicle = {
type: "vehicle",
describe() { return `This is a ${this.type}`; }
};
const car = Object.create(vehicle);
car.type = "car";
car.drive = function () { return `${this.describe()} that drives.`; };
console.log(car.drive()); // "This is a car that drives."Car inherits describe from vehicle and overrides type with its own value. When car.drive() calls this.describe(), JavaScript walks the chain, finds describe on vehicle, and runs it with this still pointing at car. That is prototype-based inheritance: objects link to other objects, and behavior is shared through the chain rather than copied.
For how constructors and classes use this mechanism to build reusable object factories, see constructor functions and class inheritance.
Rune AI
Key Insights
- Every object has an internal [[Prototype]] link to another object or null.
- Property lookup walks the chain from the object upward until the property is found or null is reached.
- Own properties shadow inherited properties with the same name.
- Object.prototype sits at the top of most chains; its prototype is null.
- Use Object.getPrototypeOf() and Object.create() for standard prototype operations.
Frequently Asked Questions
Can an object have no prototype?
What happens at the end of the prototype chain?
Is the prototype chain the same as the scope chain?
Conclusion
The prototype chain is the linked list of objects that JavaScript walks to find properties. Every object points to another object through its [[Prototype]] until the chain reaches null. When you access obj.something, JavaScript first checks obj itself, then walks the chain until it finds the property or reaches null. This is how inheritance works in JavaScript: not by copying, but by linking objects together through prototypes.
More in this topic
Using Decorators for Logging in JS Architecture
Learn how JavaScript decorators wrap class methods to add logging without touching the original code, including setup with Babel and how execution order works.
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.