Understanding Prototypes, Prototype Chaining, and Prototype Inheritance in JavaScript

Introduction
Have you ever wondered how strings, arrays, or objects "know" which methods they can use — like .toUpperCase()
for strings or .sort()
for arrays? These methods are never manually defined in your own code, yet they’re available out of the box.
This behaviour is made possible by JavaScript’s prototype system, more specifically through prototype inheritance.
In JavaScript, every object can inherit properties from another object, known as its prototype. This system enables a powerful and flexible object model without relying on traditional class-based inheritance, like in languages such as Java or Python.
How to Access a Prototype’s Properties and Methods
Each object in JavaScript contains an internal [[Prototype]]
property — a reference to another object from which it can inherit methods and properties.
Although [[Prototype]]
is internal and not directly accessible in code, JavaScript provides ways to work with it:
Using Object.getPrototypeOf()
const arr = [1, 2, 3];
console.log(Object.getPrototypeOf(arr)); // Logs Array.prototype
Deprecated but Common: __proto__
console.log(arr.__proto__); // Also logs Array.prototype
The prototype of an object contains methods like .push()
, .map()
, and .filter()
for arrays — even though these methods aren’t explicitly defined on the array instance itself.
The Prototype Chain
When you try to access a property or method on an object:
JavaScript first checks if the property exists directly on the object.
If not, it looks at the object’s prototype.
Then, it looks at the prototype’s prototype.
This continues until it either finds the property or reaches the end of the chain (
null
).
This series of lookups is known as the prototype chain.
Let’s explore how this works with different JavaScript types.
Prototype Chain for Plain Objects
const user = { name: "Jake" };
console.log(Object.getPrototypeOf(user)); // Object.prototype
console.log(Object.getPrototypeOf(Object.getPrototypeOf(user))); // null
Chain:
user → Object.prototype → null
Prototype Chain for Arrays
const arr = [1, 2, 3];
console.log(Object.getPrototypeOf(arr)); // Array.prototype
console.log(Object.getPrototypeOf(Object.getPrototypeOf(arr))); // Object.prototype
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(arr)))); // null
Chain:
arr → Array.prototype → Object.prototype → null
Prototype Chain for Functions
function greet() {
console.log("Hello");
}
console.log(Object.getPrototypeOf(greet)); // Function.prototype
console.log(Object.getPrototypeOf(Object.getPrototypeOf(greet))); // Object.prototype
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(greet)))); // null
Chain:
greet → Function.prototype → Object.prototype → null
Prototype Chain for Strings
const str = "hello";
console.log(Object.getPrototypeOf(str)); // String.prototype
console.log(Object.getPrototypeOf(Object.getPrototypeOf(str))); // Object.prototype
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(str)))); // null
Chain:
str → String.prototype → Object.prototype → null
Demonstrating Prototypical Inheritance
Let’s look at a custom example that illustrates how one object can inherit properties and methods from another using prototypes.
let basePerson = {
name: 'Ananya',
age: 28,
introduce: function () {
console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old.`);
}
};
let developer = {
name: 'Rohit'
};
// Manually setting the prototype (not recommended for production use)
developer.__proto__ = basePerson;
// developer can now access methods and properties from basePerson
developer.introduce(); // Output: Hi, I'm Rohit and I'm 28 years old.
console.log(developer.name); // Rohit
console.log(developer.age); // 28
What’s happening here?
developer
does not have anintroduce()
method orage
property.When
developer.introduce()
is called, JavaScript looks up the method in thedeveloper
object.It doesn’t find it there, so it checks the prototype —
basePerson
.It finds the method and calls it in the context of
developer
, sothis.name
is"Rohit"
andthis.age
is inherited as28
.
This is a practical example of prototypical inheritance in action.
JavaScript: A Prototype-Based Language
JavaScript is not a class-based language like Java or Python. Instead, it uses prototypal inheritance as its core mechanism for inheritance and reuse.
Here’s how it works:
Every object has an internal reference to its prototype (
[[Prototype]]
).This forms a chain of objects.
At the top of every chain is
Object.prototype
, and its prototype isnull
.
Even arrays, strings, and functions ultimately inherit from Object.prototype
.
JavaScript Classes: Just Syntactic Sugar
With ES6, JavaScript introduced the class
keyword to provide a cleaner, more familiar syntax for object-oriented code. However, JavaScript classes are just a wrapper over the prototype system.
Using class syntax
class Alien {
constructor(name, phrase) {
this.name = name;
this.phrase = phrase;
}
sayPhrase() {
console.log(this.phrase);
}
fly() {
console.log("Zzzzzziiiiiinnnnnggggg!!");
}
}
const alien1 = new Alien("Ali", "I'm Ali the alien!");
alien1.sayPhrase(); // I'm Ali the alien!
Equivalent using constructor and prototypes
function Alien(name, phrase) {
this.name = name;
this.phrase = phrase;
}
Alien.prototype.sayPhrase = function () {
console.log(this.phrase);
};
Alien.prototype.fly = function () {
console.log("Zzzzzziiiiiinnnnnggggg!!");
};
const alien1 = new Alien("Ali", "I'm Ali the alien!");
alien1.sayPhrase(); // I'm Ali the alien!
Both patterns behave identically — the class syntax is simply more readable and structured.
Summary
JavaScript uses prototypal inheritance, not class-based inheritance.
Every object has a
[[Prototype]]
, forming a prototype chain for lookups.Property and method access walks up the chain until it’s found or
null
is reached.Built-in objects like arrays, strings, and functions all follow this inheritance path.
JavaScript classes (
class
) are syntactic sugar over this prototype system.
Thank you for reading!
If you found this blog helpful, feel free to leave a comment or share it with others.
**Follow me for more deep dives into JavaScript and web development topics.
Subscribe to my newsletter
Read articles from Deepthi Purijala directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Deepthi Purijala
Deepthi Purijala
Full Stack Developer with hands-on experience of more than 1 year. Proficient in both Back-end and Front-end technologies, with a strong commitment to delivering high-quality code