Object-Oriented Programming in JavaScript

Search for a command to run...

No comments yet. Be the first to comment.
Introduction If you've ever built something with vanilla JavaScript and had to update the UI frequently, you already know the pain. You call document.getElementById, change some text, update a class,
Introduction If you've ever installed and tried out Linux after seeing a cool hacking sequence in a sci-fi movie, you know that opening it feels like stepping into a strange city with many roads named

Introduction Most JavaScript confusion around this comes from one wrong assumption: that this depends on where a function is defined. It doesn't. It depends on who called the function. That one shift

Introduction JavaScript gives you objects and arrays out of the box, and for a long time those two were the default answer to almost every data storage problem. Objects for key-value pairs, arrays for

Introduction Most JavaScript codebases are full of code like this: const user = { name: "Sara", age: 28, city: "Mumbai" }; const name = user.name; const age = user.age; const city = user.city; Three

If you've been writing JavaScript for a while, you've probably reached a point where your code starts feeling messy. Variables everywhere, functions loosely scattered around, and duplicated logic in three different places. OOP is one way to bring order to that chaos.
Think about how a car manufacturer works. They don't build each car from scratch, deciding on the fly where the steering wheel goes. They create a blueprint first. That blueprint defines what every car will have: an engine, four wheels, a color, a speed limit. Then they stamp out as many cars as they need from that blueprint.
In JavaScript, a class is the blueprint. An object is the car.
Every object you create from a class gets its own copy of the properties, but they all follow the same structure.
Here's a basic Car class:
class Car {
constructor(brand, color) {
this.brand = brand;
this.color = color;
}
describe() {
console.log("This is a " + this.color + " " + this.brand + ".");
}
}
Nothing runs yet. This is just the blueprint.
To actually make a car, you use the new keyword:
const myCar = new Car("Toyota", "red");
const yourCar = new Car("Honda", "blue");
myCar.describe(); // This is a red Toyota.
yourCar.describe(); // This is a blue Honda.
Both myCar and yourCar are objects created from the same Car class. Same structure, different data. That's the point of reusability.
The constructor is a special method that runs automatically when you create a new object. You use it to set up the initial values.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const alice = new Person("Alice", 30);
console.log(alice.name); // Alice
console.log(alice.age); // 30
this refers to the specific object being created. When alice is created, this.name becomes alice.name. When you create a second person, this refers to that one instead.
Methods are functions that belong to a class. They define what an object can do.
class Student {
constructor(name, grade) {
this.name = name;
this.grade = grade;
}
introduce() {
console.log("Hi, I'm " + this.name + " and I'm in grade " + this.grade + ".");
}
isPassing() {
return this.grade >= 50;
}
}
const raj = new Student("Raj", 72);
raj.introduce(); // Hi, I'm Raj and I'm in grade 72.
console.log(raj.isPassing()); // true
You're not repeating the logic for isPassing every time you check a student. Write it once in the class, use it on any object.
Say you need 50 student objects. Without classes, you'd either write 50 objects by hand or build some awkward factory function. With a class, you just do:
const students = [
new Student("Priya", 88),
new Student("Arjun", 45),
new Student("Meera", 91),
];
students.forEach(s => {
console.log(s.name + ": " + (s.isPassing() ? "Pass" : "Fail"));
});
Same structure, consistent behavior, zero repetition.
Encapsulation means bundling data (properties) and behavior (methods) into one place. Instead of having a studentName variable floating somewhere and a checkGrade function somewhere else, you keep everything inside the class where it belongs.
class BankAccount {
constructor(owner, balance) {
this.owner = owner;
this.balance = balance;
}
deposit(amount) {
this.balance += amount;
console.log("Deposited " + amount + ". New balance: " + this.balance);
}
withdraw(amount) {
if (amount > this.balance) {
console.log("Insufficient funds.");
} else {
this.balance -= amount;
console.log("Withdrew " + amount + ". New balance: " + this.balance);
}
}
}
const account = new BankAccount("Nisha", 1000);
account.deposit(500); // Deposited 500. New balance: 1500
account.withdraw(200); // Withdrew 200. New balance: 1300
The logic for deposits and withdrawals lives inside the class. Anyone using a BankAccount object doesn't need to think about how the math works. They just call deposit or withdraw.
That's encapsulation. The object manages its own state, and exposes clean methods to interact with it.
Here's a quick summary of the pieces:
A class is a template or blueprint
The constructor runs when you create a new object and sets initial values
Methods are functions defined inside the class
Objects are instances created from the class using new
Encapsulation means keeping related data and behavior in one place
OOP doesn't solve every problem, and JavaScript has other patterns too. But once your programs get complex enough that you're managing multiple entities with shared behavior, classes are worth knowing well.