Prototype Chain
The chain of linked objects that powers JavaScript inheritance.
Chain Visualization
Objects linked in a chain, each inheriting from the next.
function Animal(name) { this.name = name; }
Animal.prototype.eat = function() { return "eating"; };
function Dog(name, breed) {
Animal.call(this, name);
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() { return "Woof!"; };
const rex = new Dog("Rex", "Lab");rex → Dog.prototype → Animal.prototype → Object.prototype → null
Built-in Chains
Every value in JavaScript has a prototype chain.
// Arrays:
[1,2,3].__proto__ === Array.prototype // true
Array.prototype.__proto__ === Object.prototype // true
// Chain: [1,2,3] → Array.prototype → Object.prototype → null
// Strings:
"hello".__proto__ === String.prototype // true
// Chain: "hello" → String.prototype → Object.prototype → null
// Functions:
function foo() {}
foo.__proto__ === Function.prototype // true
// Chain: foo → Function.prototype → Object.prototype → null
// That's why arrays have .map(), strings have .slice(),
// and everything has .toString() — it's inherited!| Value | Chain |
|---|---|
| [1, 2] | → Array.prototype → Object.prototype → null |
| "hello" | → String.prototype → Object.prototype → null |
| 42 | → Number.prototype → Object.prototype → null |
| function(){} | → Function.prototype → Object.prototype → null |
| {} | → Object.prototype → null |
instanceof
Checks if an object's prototype chain contains a constructor's prototype.
function Animal() {}
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
const rex = new Dog();
rex instanceof Dog; // true
rex instanceof Animal; // true
rex instanceof Object; // true
// instanceof walks up the chain:
// rex.__proto__ === Dog.prototype? ✓ → true
// rex.__proto__.__proto__ === Animal.prototype? ✓ → true
// Arrays:
[] instanceof Array; // true
[] instanceof Object; // true (Array inherits from Object)💡 instanceof checks the entire chain, not just the direct prototype. For exact type checking, use Object.getPrototypeOf(obj) === X.prototype.
Property Shadowing
Own properties override inherited ones with the same name.
const parent = { color: "blue", size: 10 };
const child = Object.create(parent);
child.color; // "blue" (inherited)
child.color = "red"; // creates OWN property
child.color; // "red" (own — shadows parent)
parent.color; // "blue" (unchanged!)Setting a property on the child creates an own property that 'shadows' the inherited one. The parent is never modified.
Extending Prototypes
Adding methods to built-in prototypes (and why you usually shouldn't).
// You CAN add to built-in prototypes:
Array.prototype.last = function() {
return this[this.length - 1];
};
[1, 2, 3].last(); // 3
// But you SHOULDN'T because:
// 1. Future JS versions might add a different .last()
// 2. Libraries might conflict
// 3. for...in loops will iterate over added properties
// ✗ Don't modify: Object.prototype, Array.prototype, etc.
// ✓ Instead, use utility functions or extend with classes⚠️ Modifying built-in prototypes is called "monkey-patching". It causes maintenance nightmares. Only polyfills (adding missing standard features to old browsers) justify it.
FAQ
Common questions about the prototype chain.