W3docs

JavaScript Prototypal Inheritance

Learn JavaScript prototypal inheritance: the hidden [[Prototype]] link, __proto__ and Object methods, the prototype chain, and property shadowing with examples.

In JavaScript, objects can inherit properties and methods from other objects through a mechanism called prototypal inheritance. Instead of copying features from a class (as in Java or C++), every object holds a hidden link to another object — its prototype — and JavaScript follows that link whenever it can't find a property on the object itself. This page covers how that hidden link works, the difference between __proto__ and Object.getPrototypeOf/setPrototypeOf, how the prototype chain is searched, the role of F.prototype for constructor functions, property shadowing, and how this behaves along the chain.

Every JavaScript object has a hidden internal property called [[Prototype]]. It is either null or a reference to another object, and that referenced object is called the object's prototype.

[[Prototype]] is an internal slot in the language specification — you can't read it with a normal property access. Instead you work with it through two public APIs:

  • The historical accessor __proto__ (a getter/setter exposed by Object.prototype).
  • The modern, recommended methods Object.getPrototypeOf(obj) and Object.setPrototypeOf(obj, proto).

The simplest way to set a prototype is with __proto__ inside an object literal. Here we make animal the prototype of rabbit, so rabbit can read animal's properties:


javascript— editable

__proto__ vs Object.getPrototypeOf / setPrototypeOf

__proto__ is a getter/setter that has long been deprecated for general use — it is only standardized for browser compatibility. In real code, prefer the explicit methods:


javascript— editable

Note the difference: __proto__ is a property accessor, while getPrototypeOf/setPrototypeOf are functions. Two practical rules:

  • __proto__ is not the same as [[Prototype]]. __proto__ is just the accessor that reads/writes the internal [[Prototype]] slot.
  • Avoid changing a prototype after an object is created. Object.setPrototypeOf and assigning obj.__proto__ are slow operations: engines heavily optimize objects whose prototype is fixed at creation time. Set the prototype once, when you build the object.

The prototype chain

The prototype's prototype can have a prototype too, forming a prototype chain. When you read obj.prop, JavaScript:

  1. Looks for prop as an own property of obj.
  2. If not found, follows [[Prototype]] and looks on the prototype.
  3. Repeats step 2 up the chain until it finds prop or reaches null.

If the chain ends at null without finding the property, the result is undefined.


javascript— editable

There are two limits on the chain: references must not form a loop (JavaScript throws if you try to create a cycle), and [[Prototype]] must be either an object or null.

Property shadowing: writing vs reading

The prototype is only consulted for reading. When you write to or delete a property, the operation always acts on the object itself, never on its prototype. Assigning a property that also exists on the prototype creates an own property that shadows (hides) the inherited one:


javascript— editable

The exception is accessor properties (getters/setters): because a setter is a function call, writing through an inherited setter runs that setter rather than creating a new own data property.

this is always the calling object

A common source of confusion: no matter where a method lives in the chain, this inside it is the object before the dot when the method was called — never the prototype it was defined on. Inherited methods therefore operate on the inheriting object's own state:


javascript— editable

This is what makes shared methods on a prototype useful: one method definition, but each object stores its own data.

Constructor functions and F.prototype

Setting [[Prototype]] by hand for every object is tedious. The classic pattern is a constructor function used with new. Every function has a regular property called prototype (written F.prototype). When you call new F(), the newly created object's [[Prototype]] is set to F.prototype.


javascript— editable

Keep F.prototype distinct from an object's [[Prototype]]: F.prototype is an ordinary property of the constructor function that supplies the [[Prototype]] for objects created with new F(). By default F.prototype is an object with a single non-enumerable constructor property pointing back to the function itself.


javascript— editable

Note: Modern ES6 class syntax is syntactic sugar over exactly this mechanism. A class declaration creates a constructor function, puts its methods on Constructor.prototype, and wires up the chain with the same [[Prototype]] links. See JavaScript Class Inheritance for the extends/super form.

Creating objects with Object.create

Object.create(proto) builds a fresh object with [[Prototype]] set to proto directly — no constructor needed. It is the most explicit way to set up inheritance, and it accepts a second argument: a property-descriptor map, the same format used by Object.defineProperties.


javascript— editable

The descriptor map lets you control flags such as writable, enumerable, and configurable — see JavaScript Property Flags and Descriptors for what each flag does. Objects made with Object.create(null) (so-called "very plain" objects) are covered in Prototype Methods, Objects Without __proto__.

Multi-level inheritance

Because each prototype can have its own prototype, you can build chains several levels deep to model more specific relationships:


javascript— editable

Inspecting and iterating the chain

To check whether an object is somewhere in another object's chain, use isPrototypeOf. To separate own properties from inherited ones, use hasOwnProperty — note that for...in walks the whole chain (enumerable properties only), while Object.keys returns own keys only.


javascript— editable

Built-in types such as arrays, functions, and dates also rely on this chain — their methods live on Array.prototype, Function.prototype, and so on. See JavaScript Native Prototypes for how the built-ins are wired together.

Summary

  • Every object has a hidden [[Prototype]] that is another object or null.
  • Read [[Prototype]] with Object.getPrototypeOf, set it with Object.setPrototypeOf; __proto__ is the legacy accessor and changing a prototype after creation is slow.
  • Reads walk up the prototype chain until the property is found or the chain ends at null; writes and deletes always act on the object itself and can shadow inherited properties.
  • this inside a method is the object the method was called on, not the prototype where it was defined.
  • new F() sets the new object's [[Prototype]] to F.prototype; ES6 class is syntactic sugar over this exact mechanism — see JavaScript Class Inheritance.

Practice

Practice
Which statements accurately describe Prototypal Inheritance in JavaScript?
Which statements accurately describe Prototypal Inheritance in JavaScript?
Was this page helpful?