The prototype chain
Back to the furniture factory. The instructions "how to assemble a chair" are not glued to every chair: they sit in the blueprint's folder, one copy for all chairs. If a worker finds no answer on the chair itself, they open the folder of its blueprint. If it is not there either, they take the factory's general handbook, one for all the furniture.
Objects in JavaScript look up properties in the same way. Node.js prints an instance of a class with its data only: Animal { name: 'Rex' } shows no greet method. And yet the call rex.greet() works. The method is not stored in the object itself:
class Animal {
constructor(name) {
this.name = name;
}
greet() {
return `I am ${this.name}`;
}
}
const rex = new Animal("Rex");
console.log(rex); // Animal { name: 'Rex' }
console.log(Object.hasOwn(rex, "name"), Object.hasOwn(rex, "greet")); // true false
console.log(Object.getPrototypeOf(rex) === Animal.prototype); // trueLet's go through the three lines of output:
console.log(rex)shows onlyname, the data of the object itself.Object.hasOwnconfirms it:nameis in the object, andgreetis not.- The last line prints
true: the prototype ofrexis the objectAnimal.prototype. That is the blueprint's folder.
Own properties
The function Object.hasOwn(obj, key) checks whether an object has an own property with that key. Such a property is written into the object itself. The property name was written by constructor, while greet is not in the object.
The prototype
Every object holds a link to its prototype: another object, or null. The function Object.getPrototypeOf returns it.
Every class has a prototype property: it holds the object that new makes the prototype of new instances. For instances of the class Animal, the prototype is the object Animal.prototype, and it holds the methods from the class body, except the static ones. That is why one method serves all instances.
Lookup along the chain
If a property is not in the object itself, JavaScript looks in the prototype, then in its prototype, and so on. These links form the prototype chain. The lookup stops at the first property found. If the chain ends at null and the property was not found, the result is undefined, with no error.
const proto = Object.getPrototypeOf(rex);
console.log(Object.getPrototypeOf(proto) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype)); // null
console.log(typeof rex.toString, rex.age); // function undefinedLet's walk up the chain of rex from the bottom:
- The object
rexitself: it holdsname. Animal.prototype: it holdsgreet.Object.prototype, shared by all objects: it holds thetoStringmethod. Sorexhas it, although neither the class nor the object declared it.- Then
null:Object.prototypehas no prototype, and the chain ends.
typeof gives "function" for both a function and a method, so typeof rex.toString prints function. The property age is in none of the links, and rex.age gives undefined.
Here the factory analogy stops working. A worker who found the instructions nowhere would report an error, while JavaScript quietly returns undefined.
After extends, the chain is one link longer: the prototype of the object Dog.prototype is Animal.prototype.
Methods added to the prototype
A prototype's properties are not copied into the object; they are looked up on every read. A method added to Animal.prototype later is seen at once by objects created earlier too:
Animal.prototype.sleep = function () {
return `${this.name} sleeps`;
};
console.log(rex.sleep()); // Rex sleepsInterviewers often ask this: "What is the prototype chain?"
The answer: every object links to its prototype, and a property read goes from the object up these links to the first match or to null.
Common mistake
An instance was copied with ..., and then a method was called on the copy:
const copy = { ...rex };
console.log(copy.name); // Rex
console.log(copy.greet()); // ✗TypeError: copy.greet is not a functionThe expression { ...rex } carries over only own properties, that is, name. The new object is a plain one, its prototype is Object.prototype, and there is no greet method in its chain. The same happens with structuredClone(rex): the object holds no methods itself, so there is no DataCloneError, but the copy gets only data. A copy with methods is created through the class: new Animal(rex.name).
Key points
- Own properties live in the object itself, and class methods live in its prototype,
Class.prototype. - A property read walks the prototype chain upward to the first match or to
null, and then the result isundefined. - Prototype properties are not copied: a method added later is visible to every instance.
- A copy made with
...gets only own properties, without the class's methods.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.