Skip to content

prototype chain

The prototype chain is the series of objects that JavaScript searches, one link at a time, when code reads a property that an object doesn’t have itself.

Each object’s prototype can have a prototype of its own, and the chain follows those links until it reaches null. A property read checks the object first, then each prototype in turn. The first match wins. A property stored on the object itself is called an own property, and it shadows any property with the same name further up. If no object in the chain has the property, the read returns undefined.

Most chains are short. An object literal links to Object.prototype, whose prototype is null. An array links to Array.prototype and then to Object.prototype. A class built with extends adds one link for each parent class. That’s how ordinary objects get methods such as .hasOwnProperty() without owning them.

The in operator checks the whole chain, and for...in loops visit inherited enumerable properties, while Object.hasOwn() checks only the object itself.

Assignment never changes a data property on a prototype. It creates an own property, unless an inherited setter or a read-only inherited property intercepts it. A chain can’t loop back on itself, so Object.setPrototypeOf() throws a TypeError when a change would create a cycle.

Example

Say a code review turns up a call to .hasOwnProperty() on an array of order IDs, and the reviewer wants to know where that method comes from:

Language: JavaScript
> const orderIds = [101, 102];
undefined

> Object.getPrototypeOf(orderIds) === Array.prototype
true
> Object.getPrototypeOf(Array.prototype) === Object.prototype
true
> Object.getPrototypeOf(Object.prototype)
null

> Object.hasOwn(Array.prototype, "hasOwnProperty")
false
> Object.hasOwn(Object.prototype, "hasOwnProperty")
true
> orderIds.discount
undefined

The lookup for .hasOwnProperty() skips the array and Array.prototype and finds the method two links up, on Object.prototype. The read of discount walks the whole chain, hits null, and returns undefined. Both lookups follow the same links:

An array's property lookup climbs to Array.prototype, then Object.prototype, where hasOwnProperty is found or null yields undefined.
Lookups Climb the Chain Until a Match or null

Inherited names also leak into checks that look like they only test an object’s own keys. A table of exchange rates keyed by a currency code from user input shows the problem:

Language: JavaScript
> const rates = { USD: 1, EUR: 0.92 };
undefined

> "toString" in rates
true
> Object.hasOwn(rates, "toString")
false

> const safeRates = Object.assign(Object.create(null), rates);
undefined
> "toString" in safeRates
false

The in check reports "toString" as a valid code because Object.prototype has a method by that name. An object created with Object.create(null) has no prototype, so lookups on it see only its own keys.

Have a question about this? Mentor AI can show you examples, compare related terms, and point you to tutorials.


By Leodanis Pozo Ramos • Updated Nov. 5, 2026