An empty array holds nothing, and yet it knows how to sort, filter and transform itself. An object created with two properties answers methods nobody wrote for it. Those abilities are not copied: they are borrowed.
The mechanism is called the prototype, and it is the only form of behavior sharing the language has, including behind the class keyword.
Definition
The prototype of an object is another object it delegates lookups to. When you read a missing property, the engine looks for it on that prototype, then on its own prototype, until it reaches null.
const list = [1, 2, 3];
console.log(Object.getPrototypeOf(list) === Array.prototype); // true
console.log(Object.getPrototypeOf(Array.prototype) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype)); // null
console.log(list.hasOwnProperty("length")); // true, own property
console.log("map" in list); // true, found further upThe array only owns its elements and its length. map and the rest live once and for all on Array.prototype, shared by every array in the program.
prototype and the prototype, two different things
The most common confusion comes from one word used for two realities. This three-column table separates them.
| Spelling | Carried by | What it is |
|---|---|---|
Product.prototype | A constructor function | The object instances will receive |
Object.getPrototypeOf(p) | Any object | The prototype it inherits from |
p.__proto__ | Any object | The same thing, legacy spelling |
Only functions carry a prototype property. It matters solely at the moment the function is called with new.
function Product(name) {
this.name = name;
}
Product.prototype.label = function () {
return "Product: " + this.name;
};
const p = new Product("Keyboard");
console.log(p.label()); // Product: Keyboard
console.log(p.hasOwnProperty("label")); // false, it sits on the prototypeWhat it changes in practice
- A method exists in a single copy. A thousand instances share the same function, not a thousand copies.
- instanceof queries the chain. It does not compare types, it walks prototypes.
- A class changes none of this. It writes the same structure with a more readable syntax.
Modifying a native prototype, for instance adding a method to Array.prototype, is a bad idea: the chosen name may collide with a future language addition, and the behavior changes everywhere.
Frequently asked questions
Why is __proto__ discouraged?
Because it is a legacy accessor, kept alive so the existing web keeps working, and it is writable. Changing the prototype of an object already in use badly degrades engine optimizations. Prefer Object.getPrototypeOf() for reading, and Object.create() at creation time.
How do I create an object with no prototype at all?
With Object.create(null). The resulting object inherits nothing, not even toString. That is useful for a dictionary fed by outside data, where a key named constructor must not collide with an inherited property.
Does delegation cost time on every read?
The lookup walks the chain, so a property three levels up takes three steps. Engines cache those paths and the cost is invisible in normal code. Our JavaScript course covers this chain before classes, in that order precisely.