Object.getPrototypeOf()
getPrototypeOf(obj) The Object.getPrototypeOf() method returns the prototype of the specified object — the value of its internal [[Prototype]] slot. This is the standard way to inspect an object’s inheritance chain without relying on the non-standard __proto__ accessor.
Understanding the prototype chain matters when you want to check inheritance relationships, implement mixin patterns, or debug why a property lookup is resolving unexpectedly. Every plain object has Object.prototype at the top of its chain; arrays have Array.prototype; class instances have their constructor’s prototype.
Syntax
Object.getPrototypeOf(obj)
Parameters
| Parameter | Type | Description |
|---|---|---|
obj | object | The object whose prototype to return |
Return value
The prototype of obj, or null if the object has no prototype (created with Object.create(null)). A null return means the object sits at the very end of its prototype chain — property lookups on it will never delegate to a parent, which makes these objects ideal for use as flat dictionaries or lookup tables where inherited properties would be unwanted noise.
Examples
Basic prototype retrieval
const proto = { greet() { return 'hello'; } };
const obj = Object.create(proto);
console.log(Object.getPrototypeOf(obj) === proto); // true
Object.create() gives you explicit control over an object’s prototype from the moment of creation. But most objects in JavaScript are created with literal syntax like {}, where the engine assigns the prototype automatically. Every plain object’s chain ends at Object.prototype, which is why common utility methods are always available.
With a plain object
const user = { name: 'Alice' };
console.log(Object.getPrototypeOf(user) === Object.prototype); // true
All object literals share Object.prototype as their prototype, which is why methods like toString() and hasOwnProperty() are available on every object. Arrays get treated differently — they receive Array.prototype instead, which adds array-specific methods like .map() and .reduce() on top of the standard object methods. Array.prototype itself inherits from Object.prototype, forming a chain that gives arrays the full set of both array and object methods.
With an array
const numbers = [1, 2, 3];
console.log(Object.getPrototypeOf(numbers) === Array.prototype); // true
Arrays, objects, and class instances all sit on a standard prototype chain, but JavaScript also lets you opt out entirely. Creating an object with Object.create(null) produces a clean dictionary with no inherited properties — not even toString() or hasOwnProperty(). This is the right choice when you need a key-value map that is safe from prototype pollution.
With null prototype
const nullProto = Object.create(null);
console.log(Object.getPrototypeOf(nullProto)); // null
Objects with a null prototype have no inherited methods at all — not even toString. They are useful as pure dictionaries when you want zero prototype pollution risk. At the opposite end of the spectrum, ES6 classes give you a structured syntax for building prototype chains. Under the hood, class is syntactic sugar — the prototype mechanism is the same one we’ve been inspecting.
Checking class inheritance
class Animal {
constructor(name) {
this.name = name;
}
}
const dog = new Animal('Rex');
console.log(Object.getPrototypeOf(dog) === Animal.prototype); // true
Class instances have their constructor’s prototype as their direct prototype. The class’s own prototype then has Object.prototype as its prototype, forming a two-level chain. This direct prototype relationship is more specific than what instanceof checks — instanceof walks the full chain and returns true if the constructor’s prototype appears anywhere, not just as the immediate parent. For precise type checks, comparing prototypes directly avoids false positives from deeper inheritance.
Common patterns
Verify object type without instanceof
function isArrayLike(obj) {
return Object.getPrototypeOf(obj) === Array.prototype;
}
console.log(isArrayLike([1, 2, 3])); // true
console.log(isArrayLike({ length: 3 })); // false
instanceof can be fooled across realms (iframes, worker contexts), but comparing prototypes directly is more precise in single-realm code. A single prototype check tells you the object’s immediate parent — sometimes you need more. Walking the full prototype chain reveals the entire property lookup path the engine follows for every access, which is invaluable when properties from different ancestors shadow each other.
Walk the prototype chain
const grandparent = { a: 1 };
const parent = Object.create(grandparent);
const child = Object.create(parent);
let current = child;
const chain = [];
while (current) {
chain.push(current);
current = Object.getPrototypeOf(current);
}
console.log(chain.length); // 3
Walking the chain lets you list every object that contributes properties to a given instance. This is how engines resolve property lookups at runtime — they traverse the chain from the object upward, stopping at the first match or at null. The older __proto__ accessor also exposes this chain, but it comes with caveats. It’s an accessor defined on Object.prototype itself, which means objects created with Object.create(null) don’t have it, and assigning to it on an object with a __proto__ property of its own creates confusing bugs.
getPrototypeOf() vs proto
Older code uses the __proto__ accessor to read and write the prototype. The accessor was non-standard for a long time and is now deprecated. Object.getPrototypeOf() is the correct way to read the prototype; Object.setPrototypeOf() is the correct way to change it.
const obj = {};
// Deprecated — avoid
console.log(obj.__proto__ === Object.prototype); // true
// Correct
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
Using the standard methods also makes intent clearer and avoids edge cases with objects that have a property literally named __proto__.
Prototype vs own properties
getPrototypeOf only returns the prototype object — it does not list any of its properties or the target object’s own properties. To inspect what’s on the prototype, combine it with Object.getOwnPropertyNames:
function Person(name) { this.name = name; }
Person.prototype.greet = function() { return `Hi, I'm ${this.name}`; };
const p = new Person('Alice');
const proto = Object.getPrototypeOf(p);
console.log(Object.getOwnPropertyNames(proto)); // ['constructor', 'greet']
See Also
- Object.create() — Create object with specified prototype
- Object.setPrototypeOf() — Change an object’s prototype
- Object.keys() — Get array of object keys