JavaScript • Object-Oriented Programming (Intro)

Prototypes & Prototype Chain — Explain prototypes and prototype chain conceptually (intro)

Discover how JavaScript objects share behaviors through a hidden chain of linked prototypes.

JavaScript emblem with code brackets, braces, and a code file.
Inside this lesson 10 sections 5 questions 5 figures

SECTION 1

Historical Context & Motivation

Most popular programming languages like Java and C++ use a system called classical inheritance, where you define a blueprint (called a class) and then create objects from it. JavaScript took a very different path. When Brendan Eich created JavaScript in 1995, he chose a model called prototypal inheritance, inspired by a lesser-known language called Self. Instead of classes serving as rigid blueprints, every JavaScript object can link directly to another object and borrow its properties. This decision made JavaScript uniquely flexible — and initially confusing for many developers.

1986 • Self Language Created

Researchers David Ungar and Randall Smith at Xerox PARC created Self, a language where objects inherit directly from other objects — no classes needed. This idea is called prototype-based inheritance.

1995 • JavaScript Is Born

Brendan Eich designed JavaScript in just 10 days at Netscape. He adopted Self's prototype-based model, giving every object a hidden link to a parent prototype object.

2009 • ECMAScript 5 & Object.create

ES5 introduced Object.create(), making it easier to set up prototype chains directly and clearly.

2015 • ES6 class Syntax

ECMAScript 2015 added the class keyword, but under the hood JavaScript still uses prototypes. Classes are simply a friendlier syntax — often called syntactic sugar.

So here's the big question this lesson addresses: if JavaScript doesn't rely on traditional class blueprints, how do objects share behavior and avoid duplicating code? The answer lies in prototypes and the prototype chain — a clever linking system that lets one object look up properties from another when it doesn't have them itself.

SECTION 2

Core Principles & Definitions

Before diving into code, you need to understand four core ideas that make JavaScript's object system tick. These ideas work together to create a powerful mechanism for sharing functionality between objects.

1

Prototype

A prototype is simply an object that other objects can look to when they need a property or method they don't have themselves. Think of it as a shared reference sheet.
2

[[Prototype]] Link

Every JavaScript object has a hidden internal link called [[Prototype]] that points to another object. You can access it using __proto__ or Object.getPrototypeOf().
3

Prototype Chain

The prototype chain is the series of linked objects JavaScript walks through when searching for a property. It keeps going up the chain until it finds the property or reaches null.
4

Property Lookup

When you access a property on an object, JavaScript first checks the object itself. If the property isn't there, it follows the prototype chain upward. This process is called delegation.
✦

KEY TAKEAWAY

Imagine you're at school and you need a calculator. First, you check your own backpack. If it's not there, you ask the person sitting next to you. If they don't have one either, they ask the person next to them, and so on until someone has a calculator — or no one does. That's exactly how the prototype chain works: JavaScript checks the object itself, then its prototype, then the prototype's prototype, all the way up until it finds the property or reaches the end of the chain (null).

SECTION 3

Visual Explanation — The Prototype Chain

The diagram below shows three objects connected through the prototype chain. A dog object links to an animal object, which links to Object.prototype, which finally links to null. When you call dog.toString(), JavaScript can't find toString on dog or animal, so it walks up to Object.prototype where the method is defined.

Prototype Chain: dog → animal → Object.prototype → nulldogname: "Buddy"breed: "Labrador"[[Prototype]] →animaltype: "mammal"speak() { ... }[[Prototype]] →Object.prototypetoString() { ... }hasOwnProperty()valueOf() { ... }[[Prototype]] → nullProperty Lookup Example: dog.speak()1. Check dog ❌2. Check animal ✅✓ Found speak() on animal — use it!If not found on animal, JavaScript would continue to Object.prototype, then to null (undefined).
The three boxes represent objects linked by their [[Prototype]] references. The bottom panel demonstrates property lookup: when dog.speak() is called, JavaScript checks dog first, doesn't find it, then walks up the chain to animal where it succeeds.

Notice that dog never needed to define speak() itself — it delegates the call up the chain. This is the fundamental magic of prototypes: objects can share methods without each one having its own copy, saving memory and keeping your code organized.

SECTION 4

How the Prototype Chain Works in Code

Let's look at exactly how JavaScript creates and navigates the prototype chain. There are a few key mechanisms you should understand: constructor functions with the .prototype property, Object.create(), and the property lookup algorithm.

Constructor Functions & .prototype

When you write a constructor function and call it with new, JavaScript automatically sets the new object's [[Prototype]] to point at the constructor's .prototype property. This is a bit confusing at first: every function in JavaScript has a .prototype property, and it's used as the template for objects created with new.

⚠

Don't Confuse These Two!

The property someFunction.prototype is a regular, visible property on a function that serves as the prototype for new objects. The hidden link [[Prototype]] (accessible via __proto__ or Object.getPrototypeOf()) is the internal link every object has that points to its parent in the chain.

The Property Lookup Algorithm

Every time you access a property like obj.someProperty, JavaScript runs a simple search algorithm. It checks the object itself first. If the property isn't found, it follows the [[Prototype]] link to the next object and checks there. This continues until it either finds the property or reaches null at the end of the chain, at which point undefined is returned.

  1. Step 1: Check if the object has its own property with that name (an "own property").
  2. Step 2: If not found, follow [[Prototype]] to the parent object and repeat Step 1.
  3. Step 3: Continue until the property is found or [[Prototype]] is null.
  4. Step 4: If the end of the chain is reached without finding the property, return undefined.

SECTION 5

Anatomy of the Prototype Chain

To fully understand the prototype chain, it helps to see what happens when you create objects using different approaches. The diagram below compares three common scenarios: a plain object literal, an object created via a constructor function, and an array. Each one has a slightly different prototype chain, but they all end at the same place — Object.prototype and then null.

Three Prototype Chains ComparedObject LiteralConstructor FunctionArray{ name: "Jo" }(your object)new Person("Jo")(instance)[1, 2, 3](array instance)Person.prototypegreet() defined hereArray.prototypepush(), map(), etc.Object.prototypetoString(), valueOf()nullAll chains end at Object.prototype → null
All three chains converge at Object.prototype before reaching null. Arrays have an extra link through Array.prototype (which gives them methods like push() and map()), while constructor-created objects pass through the constructor's .prototype.

This is why every JavaScript object has access to methods like toString() and hasOwnProperty() — they're defined on Object.prototype, which sits at the top of every prototype chain. Arrays additionally inherit array-specific methods from Array.prototype, and functions inherit from Function.prototype. The chain always flows upward and always ends at null.

Object TypePrototype ChainChain Length
{ }obj → Object.prototype → null2 links
new Person()instance → Person.prototype → Object.prototype → null3 links
[1, 2, 3]arr → Array.prototype → Object.prototype → null3 links
Object.create(null)obj → null1 link

Common prototype chains and their lengths

SECTION 6

Worked Example — Building a Prototype Chain

Let's walk through creating a prototype chain step by step using Object.create() and then trace how JavaScript looks up a property.

Creating and Tracing a Prototype Chain

  1. 1

    Step 1 — Define the Base Object

    We start by creating a base object called vehicle with a shared method: const vehicle = { wheels: 4, start() { return 'Vroom!'; } };
    vehicle has two own properties: wheels and start.
  2. 2

    Step 2 — Create a Child Object with Object.create()

    We use Object.create(vehicle) to create a new object whose [[Prototype]] points to vehicle: const car = Object.create(vehicle); car.brand = 'Toyota';
    car has one own property (brand) and inherits from vehicle.
  3. 3

    Step 3 — Access an Inherited Property

    Now let's access car.wheels. JavaScript first checks car — does it have wheels as an own property? No. So JavaScript follows the [[Prototype]] link to vehicle and checks there. Found it!
    car.wheels returns 4 (inherited from vehicle).
  4. 4

    Step 4 — Verify with hasOwnProperty()

    We can confirm the difference between own and inherited properties: car.hasOwnProperty('brand') // true car.hasOwnProperty('wheels') // false The method hasOwnProperty() itself is inherited from Object.prototype — demonstrating the chain in action.
    brand is an own property; wheels is inherited.
  5. 5

    Step 5 — Property Shadowing

    What if we set car.wheels = 3? This creates a new own property on car that shadows (hides) the inherited one. The original vehicle.wheels remains 4 — it is not modified.
    car.wheels is now 3 (own); vehicle.wheels is still 4.

SECTION 7

Prototypal vs. Classical Inheritance

If you've heard of object-oriented programming in languages like Java or C++, you may be used to classical inheritance where classes define structure and subclasses extend them. JavaScript's prototypal approach is fundamentally different, though the ES6 class syntax makes them look similar on the surface. Here's how they compare.

FeatureClassical (Java, C++)Prototypal (JavaScript)
BlueprintClasses define structure at compile timeObjects link to other objects at runtime
InheritanceCopies structure from parent classDelegates lookups to prototype via chain
FlexibilityFixed once compiledCan modify prototypes at any time
MemoryEach object has its own copy of methodsObjects share methods via prototype
Syntaxclass Dog extends AnimalObject.create(), constructors, or ES6 class (sugar)

Classical inheritance vs. prototypal inheritance

✦

KEY TAKEAWAY

Think of classical inheritance like a factory stamping out identical parts from a mold — once the mold is set, every part is the same. Prototypal inheritance is more like a family: you don't have copies of your parents' skills, but you can call them up and ask for help whenever you need it. The connection is live and dynamic.

SECTION 8

Connection to Advanced Concepts

Understanding prototypes is the foundation for many advanced JavaScript topics. The ES6 class keyword, for example, doesn't introduce a new inheritance model — it's just a cleaner way to set up prototype chains. Under the hood, class Dog extends Animal is doing the exact same thing as manually linking prototypes.

What You Learn NowWhat It Unlocks Next
Prototype chain and property lookupUnderstanding how ES6 classes really work under the hood
Object.create()Composition over inheritance patterns and mixins
Property shadowingMethod overriding in class hierarchies and polymorphism
Constructor functions and .prototypeThe new keyword mechanics, instanceof operator

How prototypes connect to advanced OOP concepts

As you advance, you'll also encounter mixins (combining behaviors from multiple sources), the delegation pattern (where objects explicitly hand off work to their prototypes), and design debates like "composition over inheritance." All of these build on the prototype foundation you're learning right now.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

In your own words, explain the difference between an object's own property and an inherited property. Why does this distinction matter when working with the prototype chain?
Show answer
An own property is stored directly on the object itself, while an inherited property belongs to one of the objects higher up in the prototype chain. When JavaScript looks up a property, it checks own properties first and only walks the chain if it doesn't find one. This matters because setting a property always creates (or updates) an own property on the target object — it never modifies the prototype. This mechanism is called property shadowing, and it prevents accidental changes to shared prototype properties that other objects depend on.

Question 2: BASIC CALCULATION

Given the following code, what does child.greet() return? Trace the prototype chain lookup. const parent = { greet() { return 'Hello!'; } }; const child = Object.create(parent); child.name = 'Alex';
Show answer
child.greet() returns 'Hello!'. Here's the lookup trace: JavaScript first checks child for a greet property. It finds only name, so it follows the [[Prototype]] link to parent. There it finds greet() and executes it. The child never needed its own copy of the function — delegation handled everything.

Question 3: INTERMEDIATE

Consider this code. What are the values of a.x, b.x, and proto.x after all lines execute? const proto = { x: 10 }; const a = Object.create(proto); const b = Object.create(proto); a.x = 20;
Show answer
a.x is 20 because setting a.x = 20 creates a new own property on a that shadows the prototype's value. b.x is still 10 because b has no own x property and still delegates to proto. proto.x remains 10 — assigning to a.x never modifies the prototype itself.

Question 4: APPLIED

You're building a simple game with character objects. All characters should share a takeDamage(amount) method that subtracts from their health property, but each character has their own name and health. Write the code using Object.create() to set this up efficiently. Explain why placing takeDamage on the prototype is better than putting it on every character object.
Show answer
You could write: const characterProto = { takeDamage(amount) { this.health -= amount; } }; then const hero = Object.create(characterProto); hero.name = 'Aria'; hero.health = 100; Placing takeDamage on the prototype means all characters share a single copy of the function in memory, rather than each character storing its own copy. If you create 100 characters, you still only have one takeDamage function. When hero.takeDamage(25) is called, JavaScript finds the method on the prototype, but this still refers to hero, so each character's own health property is modified correctly.

Question 5: CRITICAL THINKING

JavaScript's Object.create(null) creates an object with no prototype at all (its [[Prototype]] is null). What are the consequences of this? What built-in methods would you lose, and when might this actually be useful?
Show answer
An object created with Object.create(null) has no link to Object.prototype, so it lacks methods like toString(), hasOwnProperty(), and valueOf(). Calling any of these would throw an error. This is useful when you need a truly "clean" dictionary or lookup table — since there are no inherited properties, you don't risk collisions with prototype method names. For example, if you used a regular object as a dictionary and someone stored a key called 'toString', it would shadow the built-in method and potentially cause bugs. With Object.create(null), every property is an own property, making it safe for arbitrary key-value storage.

SUMMARY

Lesson Summary

Summary

Every JavaScript object has a hidden [[Prototype]] link that points to another object called its prototype. When you access a property on an object and it isn't found as an own property, JavaScript walks up the prototype chain — checking each linked object — until it either finds the property or reaches null. This process is called delegation, and it's how JavaScript objects share behavior without duplicating code.

Unlike classical inheritance where classes copy structure, JavaScript's prototypal inheritance creates live links between objects. You can set up chains using Object.create(), constructor functions with .prototype, or the ES6 class syntax (which is syntactic sugar over prototypes). When you assign a property to an object, it creates an own property that shadows the inherited one without modifying the prototype. All chains ultimately end at Object.prototype → null.

Varsity Tutors • JavaScript • Prototypes & Prototype Chain