Understanding Prototypes in JavaScript

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__
vsprototype
- 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`)
Here:
student
doesn’t havegreet()
.- JavaScript looks up the prototype chain (to
person
) and finds it there.
The Prototype Chain
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)
Diagrammatically:
student --> person --> Object.prototype --> null
When you access student.greet()
, JS will:
- Look for
greet
instudent
. - Not found? Check
student.__proto__
(which isperson
). - Still not found? Go up again (to
Object.prototype
). - If nowhere to be found →
undefined
.
Function Prototypes vs Object Prototypes
This often confuses people: there’s a difference between prototype
and __proto__
.
__proto__
: Property of the object instance. Points to its prototype.prototype
: Property of the constructor function. Used to set the__proto__
of 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__
is the prototype from which it inherits — in this case,Animal.prototype
.Animal.prototype.speak
is shared among all instances.
ES6 Classes & Prototypes
ES6 introduced the class
syntax, but it’s syntactic sugar over the same prototypal system.
class Vehicle {
drive() {
console.log("Vroom!");
}
}
const car = new Vehicle();
car.drive(); // "Vroom!"
console.log(Object.getPrototypeOf(car) === Vehicle.prototype); // true
So even with class
, JavaScript still uses prototypes underneath.
Why Use Prototypes?
Using prototypes helps with:
- Memory efficiency — methods are shared across instances.
- Performance — avoids recreating functions for every object.
- Structure — clear inheritance paths.
Imagine this mistake:
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 new function. Instead:
User.prototype.sayHi = function () {
console.log("Hi!");
};
Now all instances share the same method.
Common Pitfalls
- Don’t manually set
__proto__
— useObject.create()
or proper inheritance. - Avoid overusing inheritance. Favor composition over inheritance when possible.
- Prototype chain lookups can be slower than direct access.
Recap
- Every object in JS has a prototype, which forms a chain.
- Prototypes allow for method and property inheritance.
- Constructor functions and ES6 classes use
prototype
to define shared behavior. - Understanding the prototype system helps you write cleaner, more performant code.
Helpful Methods
Method | Description |
---|---|
Object.create(proto) | Creates a new object with the specified prototype |
Object.getPrototypeOf(obj) | Returns the prototype of the object |
Object.setPrototypeOf(obj, proto) | Sets the prototype (not recommended for performance) |
instanceof | Checks prototype chain |
hasOwnProperty() | Checks if a property exists directly on the object, not via prototype |
Prototype Debugging Tips
Use browser DevTools! Console commands like these are your friends:
Object.getPrototypeOf(obj)
obj.hasOwnProperty('prop')
console.dir(obj)
If you’re still thinking in classes, you’re missing out on JavaScript’s true inheritance model.
Hi, my name is Toni Naumoski, and I’m a Senior Frontend Developer with a passion for blending code and design. With years of experience as a Frontend Developer, Web Designer, and Creative Technologist, I specialize in crafting unique, responsive, and detail-oriented websites and web applications that stand out. I bring deep expertise in HTML, CSS, and JavaScript—working fluently with modern frameworks like React, Angular, and Vue, as well as animation libraries like GSAP. My creative side thrives in Photoshop and Figma, and I enjoy extending functionality using tools like Express.js and ChatGPT. My work is guided by high integrity, strong communication, a positive attitude, and a commitment to being a reliable collaborator. I take pride in delivering high-quality digital experiences that are both technically solid and visually compelling.
Post Comment