# How Does Prototypal Inheritance Work in JavaScript? A Complete Technical Guide

> Unlock the secrets of prototypal inheritance in JavaScript. Understand the [[Prototype]] chain and how JavaScript finds properties efficiently. Master this core concept.

- Repository: [H5BP/Front-end-Developer-Interview-Questions](https://github.com/h5bp/Front-end-Developer-Interview-Questions)
- Tags: deep-dive
- Published: 2026-03-05

---

**Prototypal inheritance in JavaScript works through a hidden `[[Prototype]]` link that forms a chain; when you access a property, the engine traverses this chain until it finds the property or reaches `null`.**

Unlike classical class-based languages, JavaScript implements inheritance via objects that serve as prototypes for other objects. This mechanism is documented in the `h5bp/Front-end-Developer-Interview-Questions` repository within [`src/questions/javascript-questions.md`](https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/main/src/questions/javascript-questions.md), where it appears as a core interview topic testing deep language understanding.

## The Prototype Chain Mechanism

Every JavaScript object has an internal slot called `[[Prototype]]` (exposed via `Object.getPrototypeOf()` or the legacy `__proto__` accessor) that references another object or `null`. When you attempt to read a property, JavaScript first checks the object itself. If the property is missing, the engine walks up the `[[Prototype]]` chain until it locates the property or exhausts the chain.

This design enables **delegation-based inheritance**—objects delegate property lookups to their prototypes rather than copying behavior.

## Constructor Functions and the prototype Property

Constructor functions provide the traditional pattern for creating prototypal inheritance. When you invoke a function with the `new` keyword, JavaScript creates an object whose `[[Prototype]]` references the constructor’s `prototype` property.

```javascript
function Person(name) {
  this.name = name;
}

Person.prototype.greet = function () {
  return `Hello, I'm ${this.name}`;
};

const alice = new Person('Alice');
console.log(alice.greet()); // "Hello, I'm Alice"

```

In this pattern, `alice` does not contain `greet` directly; the method lives once on `Person.prototype`, and all instances share it through the prototype chain.

## Creating Inheritance with Object.create()

For direct object-to-object inheritance without constructors, `Object.create(proto)` explicitly sets the `[[Prototype]]` of a new object to `proto`.

```javascript
const vehicle = {
  wheels: 4,
  drive() { return 'vroom'; }
};

const car = Object.create(vehicle);
car.color = 'red';

console.log(car.drive()); // 'vroom' (inherited from vehicle)
console.log(car.wheels);  // 4 (inherited from vehicle)

```

To establish deeper hierarchies with constructors, manually link prototypes using `Object.create()` within the [`src/_data/helpers.js`](https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/main/src/_data/helpers.js) pattern of utility composition:

```javascript
function Shape(name) {
  this.name = name;
}

Shape.prototype.area = function () {
  return 0;
};

function Circle(radius) {
  Shape.call(this, 'circle'); // Inherit instance properties
  this.radius = radius;
}

// Set up the prototype chain
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle; // Restore constructor reference

Circle.prototype.area = function () {
  return Math.PI * this.radius ** 2;
};

const c = new Circle(5);
console.log(c.area()); // 78.5398...

```

## ES6 Classes: Syntactic Sugar Over Prototypes

The `class` and `extends` keywords introduced in ES2015 do not alter the underlying prototypal mechanism; they provide cleaner syntax for the same delegation patterns found in [`config/eleventy.config.js`](https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/main/config/eleventy.config.js) and other modern JavaScript files.

```javascript
class Animal {
  constructor(species) {
    this.species = species;
  }
  speak() {
    return `${this.species} makes a sound`;
  }
}

class Dog extends Animal {
  constructor(name) {
    super('dog');
    this.name = name;
  }
  speak() {
    return `${this.name} barks`;
  }
}

```

Under the hood, `extends` still manipulates `[[Prototype]]` links between `Dog.prototype` and `Animal.prototype`, and `super()` invokes `Animal.call(this, ...)`.

## Memory Efficiency and Dynamic Behavior

Prototypal inheritance offers two architectural advantages critical for high-performance applications referenced in the [`README.md`](https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/main/README.md):

- **Memory efficiency:** Shared methods exist once on the prototype, not duplicated across every instance.
- **Dynamic updates:** Adding methods to a prototype at runtime immediately makes them available to all existing instances.

## Summary

- **Prototypal inheritance** delegates property lookups through a chain of objects linked via `[[Prototype]]`.
- **Constructor functions** use the `prototype` property to share methods across instances created with `new`.
- **Object.create(proto)** creates objects with an explicit prototype without using constructors.
- **ES6 classes** are syntactic sugar that compiles down to the same prototype-based delegation.
- The implementation files [`src/questions/javascript-questions.md`](https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/main/src/questions/javascript-questions.md) and [`src/_data/helpers.js`](https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/main/src/_data/helpers.js) demonstrate how these patterns appear in real-world codebases.

## Frequently Asked Questions

### What is the difference between `__proto__` and `prototype`?

`prototype` is a property of constructor functions that becomes the `[[Prototype]]` of instances created with `new`, while `__proto__` (or `Object.getPrototypeOf`) is the accessor for an object's actual internal `[[Prototype]]` link. Every object has `[[Prototype]]`, but only functions have `prototype`.

### Why is `Object.setPrototypeOf` discouraged in production code?

Mutating an object's prototype after creation with `Object.setPrototypeOf` or `obj.__proto__ = proto` de-optimizes the engine's hidden class representations, causing significant performance degradation in V8 and other JavaScript engines. Set prototypes at object creation time using `Object.create` instead.

### How does property lookup actually traverse the chain?

When accessing `obj.property`, JavaScript checks:
1. The object itself.
2. Its `[[Prototype]]`.
3. The prototype's `[[Prototype]]`, continuing until reaching `null`.
If the property is found as a method, `this` remains bound to the original object, enabling method inheritance while maintaining instance context.

### Does JavaScript have multiple inheritance?

JavaScript objects can only inherit directly from one prototype chain (`[[Prototype]]` is a single reference). However, you can mix behaviors using composition patterns—assigning methods from multiple source objects to a single target—rather than true multiple inheritance.