Object Oriented Programming (OOP) in JavaScript
JavaScript wasn't originally built as an object-oriented language in the classical sense. Underneath the classes we use today, there's still a prototype-based system running, and understanding that foundation helps you write more predictable code.
Classes: the visible face
Since ES6, JavaScript lets you declare classes with syntax familiar to anyone coming from other languages:
class Vehicle {
constructor(brand) {
this.brand = brand;
}
describe() {
return `This vehicle is a ${this.brand}`;
}
}
const car = new Vehicle('Toyota');
console.log(car.describe());
This looks like textbook object-oriented programming. But underneath, it's still prototypes.
Prototypes: what's underneath
Every object in JavaScript holds an internal reference to another object, its prototype, from which it inherits properties and methods. When you access a property an object doesn't have directly, JavaScript looks it up along the prototype chain.
console.log(car.__proto__ === Vehicle.prototype); // true
This is why every object created with new Vehicle() shares the same describe method without duplicating it in memory: it lives once, on the prototype.
Inheritance with extends
Inheritance between classes uses extends, which really just connects the prototype chains underneath:
class Car extends Vehicle {
constructor(brand, doors) {
super(brand);
this.doors = doors;
}
}
super() calls the parent class's constructor before adding Car's own properties.
Why it matters
Understanding that classes are a layer of syntax over prototypes avoids surprises — like why modifying Vehicle.prototype affects instances that already exist, or why certain composition patterns behave differently than you'd expect in a purely class-based language.