Prototype: The Real Worker Behind the Scenes of Classes
If you've ever wondered how JavaScript handles inheritance under the hood, the answer is prototype. But before we get into that, let’s start with constructor functions—the OG way of creating objects.
Constructor Functions: The Old-School Blueprint
Before class was introduced in ES6, JavaScript developers used constructor functions to create objects with shared properties and methods.
function Person(name) {
this.name = name;
this.greet = function () {
return `Hello, I'm ${this.name}`;
};
}
const user1 = new Person("John");
const user2 = new Person("Jane");
console.log(user1.greet()); // Hello, I'm John
Seems fine, right? But there's a problem—every instance gets its own copy of the greet function which takes more space in memory. That’s inefficient! This is where prototype comes in.
Prototype: The Hidden Worker
JavaScript provides a way to share methods across all instances without duplicating them in memory, by attaching them to the prototype of a constructor function.
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
return `Hello, I'm ${this.name}`;
};
const user1 = new Person("John");
const user2 = new Person("Jane");
console.log(user1.greet()); // Hello, I'm John
console.log(user2.greet()); // Hello, I'm Jane
console.log(user1.greet === user2.greet); // true (same function, shared)
Now, all Person instances share the greet method instead of creating a new copy each time!🔥
So What is __proto__?
Every object in JavaScript has a hidden __proto__ property that links it to its constructor’s prototype.
console.log(user1.__proto__ === Person.prototype); // true
This forms the prototype chain, where JavaScript looks for properties/methods in an object, then in its prototype, then in Object.prototype, and so on (this is the power behind inheritance, objects inherit behavior via prototypes instead of class-based inheritance like in Java or Python.)
Enter ES6 Classes: A Cleaner Syntax
While prototype-based inheritance worked, it wasn’t the most intuitive. So JavaScript introduced class to make things cleaner, but under the hood, it still uses prototypes!
class Person {
constructor(name) {
this.name = name;
}
greet() {
return `Hello, I'm ${this.name}`;
}
}
const user1 = new Person("John");
console.log(user1.greet()); // Hello, I'm John
console.log(user1.__proto__ === Person.prototype); // true
The class syntax is just syntactic sugar over prototype-based inheritance—it makes code easier to read and write, but prototype is still doing all the work behind the scenes.
To Conclude
So next time you write a class, just remember that prototype is still the one doing all the heavy lifting! 🚀