Understanding JavaScript Prototypes: How Inheritance Works

posted Originally published at thefrontendarchitect.com 3 min read

Why You Should Understand Prototypes

When you start learning JavaScript, you’ll often hear this phrase:

In JavaScript, everything is an object.

But what’s often left out is how JavaScript handles inheritance not through classes (traditionally), but through prototypes.

In this post, we’ll explore:

  • What prototypes are
  • How the prototype chain works
  • __proto__ vs prototype
  • How JavaScript uses prototypes for inheritance
  • How ES6 classes relate to prototypes
  • When and why you should care

What Is a Prototype?

In JavaScript, every object has an internal link to another object called its prototype.
This prototype object can have its own prototype, forming a prototype chain. The chain ends when a prototype is null.

Think of it like a fallback mechanism — if a property or method isn’t found on an object, JavaScript looks up the chain.

Example

const person = {
  greet() {
    return "Hello!";
  }
};

const student = Object.create(person);
student.name = "Toni";

console.log(student.name);      // "Toni"
console.log(student.greet());  // "Hello!" (inherited from `person`)

Explanation

  • student doesn’t have greet()
  • JavaScript looks up the prototype chain (to person) and finds it there

The Prototype Chain in JavaScript

Every object in JavaScript has a hidden property [[Prototype]] (accessible via proto) that points to its prototype.

const obj = {};
console.log(obj.__proto__);             // Same as Object.prototype
console.log(obj.__proto__.__proto__);  // null (end of chain)

Diagram

student → person → Object.prototype → null

When you access student.greet(), JS will:

  • Look for greet in student
  • Not found? Check student.proto (which is person)
  • Still not found? Go up again (to Object.prototype)
  • If nowhere to be found → undefined

__proto__ vs prototype : What’s the Difference?

This is a common confusion for new developers.

__proto__ The internal prototype of an instance

prototype A property on constructor functions used to create new instances

Example with Constructor

function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function () {
  return `${this.name} makes a noise.`;
};

const dog = new Animal("Rex");

console.log(dog.speak()); // "Rex makes a noise."
console.log(dog.__proto__ === Animal.prototype); // true

dog.__proto__ points to Animal.prototype, where speak() is defined.

ES6 Classes & Prototypes

class Vehicle {
  drive() {
    console.log("Vroom!");
  }
}

const car = new Vehicle();
car.drive(); // "Vroom!"

console.log(Object.getPrototypeOf(car) === Vehicle.prototype); // true

Even with class, JavaScript uses prototypes behind the scenes.

Why Use Prototypes?

Using prototypes provides several advantages:

  • Memory efficiency — methods are shared across instances
  • Performance — avoids recreating functions for every object
  • Structure — clear inheritance paths

Anti-pattern Example

function User() {
  this.sayHi = function () {
    console.log("Hi!");
  };
}

const u1 = new User();
const u2 = new User();

console.log(u1.sayHi === u2.sayHi); // false 

Each sayHi is a separate function. That’s inefficient.

Recommended Prototype Approach

function User() {}
User.prototype.sayHi = function () {
  console.log("Hi!");
};

const u1 = new User();
const u2 = new User();

console.log(u1.sayHi === u2.sayHi); // true 

Common Pitfalls When Using Prototypes

Avoid these mistakes when working with prototypes:

  • Don’t manually set __proto__ — use Object.create() or a proper constructor
  • Don’t overuse inheritance — favor composition where possible
  • Prototype chain lookups are slower than direct property access

Helpful Built-in Methods for Working with Prototypes

Object.create(proto)Creates a new object with a given prototype

Object.getPrototypeOf(obj)Returns the prototype of obj

Object.setPrototypeOf(obj, proto)Sets the prototype (avoid for performance reasons)

instanceofChecks if proto exists in the object’s prototype chain

hasOwnProperty()Checks if the property exists on the object itself, not its prototype

Debugging Prototype Issues

Use DevTools in your browser to inspect prototype chains.

Try these in the console:

Object.getPrototypeOf(obj);
obj.hasOwnProperty('prop');
console.dir(obj);

Conclusion

Understanding how JavaScript handles prototypes gives you the power to write clean, reusable, and performant code.

Key Takeaways

  • Every object in JS has a prototype, forming a chain
  • Inheritance flows up the prototype chain
  • Constructor functions and class use prototypes
  • Prototypes help reduce memory usage and improve structure
  • Don’t manually tinker with __proto__ — use proper patterns

If you’re still thinking only in classes, you’re missing JavaScript’s true inheritance model.

If you read this far, tweet to the author to show them you care. Tweet a Thanks
0 votes
0 votes

More Posts

What is Javascript and How It Powers Modern Websites

Sangy K - Aug 12

JavaScript: Array Iteration and DOM Manipulation in Game Development

Michael Larocca - Oct 13

Still.js - A way to leverage Vanilla JavaScript for Complex and Enterprise Level Web Development

Nakassony Bernardo - Jun 29

The Unchaining: My Personal Journey Graduating from jQuery to Modern JavaScript

kitfu10 - May 20

From Vanilla Template to Still.js Components: A Full Build and Deployment Guide

Nakassony Bernardo - Aug 10
chevron_left