Skip to content

Intermediate · Scope, this, prototypes and classes · topic 23 of 61 · 25 min

Prototypes and the prototype chain

Explanation

Every object has a hidden link to another object called its prototype. When you read a property the object does not have, JavaScript looks in its prototype, then that object's prototype, and so on: this is the prototype chain. It is how arrays get map and push, and how classes share methods.

Where do methods like push come from?

You create an array with [1, 2] and can immediately call .push or .map, but you never put those methods on it. They live on a shared object, Array.prototype. Your array has a hidden link to it. This link is called the object's prototype, written [[Prototype]] in the specification.

Property lookup walks the chain

When you read obj.x, the engine checks obj itself. If x is not there, it checks obj's prototype, then the prototype's prototype, until it finds x or reaches null at the end of the chain (then the result is undefined). Writing obj.x = 1 always creates or changes the property on obj itself.

javascript
const nums = [1, 2];
console.log(Object.getPrototypeOf(nums) === Array.prototype);        // true
console.log(Object.getPrototypeOf(Array.prototype) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype));                // null (end)
// nums → Array.prototype → Object.prototype → null

Object.create: choose the prototype

javascript
const animal = {
  speak() { return `${this.name} makes a sound`; },
};
const dog = Object.create(animal); // dog's prototype is animal
dog.name = 'Tommy';
console.log(dog.speak());            // Tommy makes a sound (found on animal)
console.log(Object.hasOwn(dog, 'speak')); // false: it is inherited

Constructor functions: the older way

Before classes (ES2015), people wrote constructor functions and called them with new. Every function has a .prototype object; objects made with new F() get F.prototype as their prototype. Methods placed on F.prototype are shared by all instances, so they exist in memory only once.

javascript
function Account(owner, balance) {
  this.owner = owner;
  this.balance = balance;
}
Account.prototype.deposit = function (amount) {
  this.balance += amount;
  return this.balance;
};
const a1 = new Account('Asha', 100);
const a2 = new Account('Ravi', 50);
console.log(a1.deposit(25));                   // 125
console.log(a1.deposit === a2.deposit);        // true: one shared function

What new does, step by step: it creates an empty object, sets its prototype to F.prototype, runs F with this = that object, and returns it.

Think of it like this: The prototype chain is like asking for a tool in a joint family. You first look in your own room; if it is not there, you ask your parents; then your grandparents. Everyone in the house uses the grandparents' one big toolbox instead of each buying their own.

Shadowing

If an object has its own property with the same name as one on the prototype, its own property wins. This is called shadowing, and it is how a class overrides an inherited method.

Careful: Never add methods to built-in prototypes such as Array.prototype or String.prototype in real projects (called "monkey patching"). Every array in the program, and in every library you use, suddenly gets your method, and a future JavaScript version may add a built-in method with the same name and different behaviour. This really happened: a proposed Array method had to be renamed because an old library had patched the prototype.
Tip: Use Object.getPrototypeOf(obj) to read a prototype. The old obj.__proto__ property still works in browsers but is a legacy feature; avoid it in new code.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Prototypes and the prototype chain · 1/6

Prototypes

In this lesson you will see how objects inherit from other objects through prototypes.

Prefer a video by a teacher? Find free videos on “javascript prototype chain explained object create” on YouTube ↗

In real life: Thousands of order objects, one copy of each method

An order-management system loads 50,000 orders into memory. If every order object carried its own copy of total(), format() and validate(), memory use would grow badly. Putting the methods on a prototype (or in a class) means 50,000 small data objects all sharing one copy of each method.

javascript
const orderMethods = { total() { return this.qty * this.price; } };
const orders = [1, 2, 3].map((n) => Object.assign(Object.create(orderMethods), { qty: n, price: 100 }));
console.log(orders.map((o) => o.total())); // [100, 200, 300]
console.log(orders[0].total === orders[2].total); // true

Practice (0/3 done)

Task 1 · Code · Javascript

Create an object cat with Object.create(animal) so that cat.speak() works, and give cat its own name "Billi".

Task 2 · Code · Javascript

Write a constructor function Product(name, price). Put a method withGst() on Product.prototype that returns price * 1.18 rounded to the nearest rupee. All products must share the same withGst function.

Task 3 · Code · Javascript

Write chainLength(obj) that returns how many prototypes are above obj before reaching null. For a plain object {} the answer is 1 (Object.prototype). For an array it is 2.

Quick quiz

Question 1

1.Where does [1, 2].map come from?

Question 2

2.What is at the very end of every normal prototype chain?

Question 3

3.Why put methods on F.prototype rather than inside the constructor?

Question 4

4.const p = { x: 1 }; const c = Object.create(p); c.x = 2; What is p.x?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Where does [1, 2].map come from?

Answer: Array.prototype

map is defined once on Array.prototype and found through the chain.

What is at the very end of every normal prototype chain?

Answer: null

Object.prototype's prototype is null, which ends the lookup.

Why put methods on F.prototype rather than inside the constructor?

Answer: All instances share one copy, saving memory

Methods created inside the constructor are copied for each object.

const p = { x: 1 }; const c = Object.create(p); c.x = 2; What is p.x?

Answer: 1

Writing c.x creates an own property on c that shadows p.x; p is unchanged.

Where do the methods of a class live?Related

Answer: On ClassName.prototype

Class methods are put on the prototype and shared.

From Classes

What is a prototype for?Related

Answer: To declare the function's signature before it is used

The compiler can then check calls.

From Functions

What does Object.keys({ a: 1, b: 2 }) return?Related

Answer: ['a', 'b']

Object.keys gives the property names.

From Objects: keys and values

What is a function prototype?Related

Answer: A declaration: the function's first line ending with a semicolon

It tells the compiler the function's name, return type and parameter types before its body appears.

From Functions: declare, define, call and return

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next: Classes →

Next steps

  1. 2 more topics in “Scope, this, prototypes and classes” before its exam: Classes, Inheritance and composition.
  2. Module 5 exam: Scope, this, prototypes and classes · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Modules, errors, JSON and dates. 61 topics left in the course before the final exam.

← Previous: How this works