Understanding Object-Oriented Programming in JavaScript

A beginner friendly guide to writing organised, reusable code, with real-life analogies.
What Is Object-Oriented Programming?
Imagine a car factory.
The factory doesn't build one car and stop. It uses a blueprint, a single design document that describes what every car should look like: 4 wheels, an engine, a colour, a model name, the ability to accelerate, the ability to brake.
From that one blueprint, the factory can produce thousands of cars. Each car is its own separate thing, one might be red, another blue, but they all share the same structure because they came from the same blueprint.
Object-Oriented Programming (OOP) works the same way.
The blueprint is called a Class
The cars produced from it are called Objects
OOP is a way of writing code where you:
Define a blueprint (class) that describes the structure and behaviour of something
Create as many objects as you need from that blueprint
Reuse your code instead of writing the same thing over and over
Without OOP, if you wanted to represent 100 students in your code, you'd write 100 separate objects by hand. With OOP, you write one Student class, and create 100 objects from it in seconds.
Four Ideas Behind OOP
OOP is built around a few core ideas. Don't worry about memorising these, just read them and let the concepts settle as you see examples.
Class — the blueprint
Object — a real thing made from the blueprint
Properties — the data (name, age, colour)
Methods — the actions (drive, brake, printDetails)
We will see all of these through examples right now.
What Is a Class?
A class is a template. It describes:
What data an object will hold (properties)
What actions an object can perform (methods)
Here is the simplest possible class in JavaScript:
class Car {
// properties and methods go here
}
That's it, a class starts with the class keyword, followed by a name (always capitalised by convention), followed by curly braces.
Convention: Class names always start with a capital letter.
Car,Person,Student, notcar,person,student.
Right now this class is empty. Let's fill it in.
The Constructor Method
When you create an object from a class, JavaScript needs to know: what should this object's starting values be?
That's the job of the constructor.
The constructor is a special method inside a class that runs automatically every time you create a new object. It sets up the object's initial properties.
class Car {
constructor(brand, colour) {
this.brand = brand;
this.colour = colour;
}
}
Let's break this down piece by piece:
constructor(brand, colour)— this method accepts two inputs when a new car is createdthis— refers to the specific object being created right now. Think ofthisas saying "this particular car"this.brand = brand— stores the incomingbrandvalue on the objectthis.colour = colour— stores the incomingcolourvalue on the object
So every Car object will have its own brand and colour, set at the moment it's created.
Creating Objects from a Class
To create an object from a class, you use the new keyword:
let car1 = new Car("Toyota", "Red");
let car2 = new Car("Honda", "Blue");
Step by step, what happens when you write new Car("Toyota", "Red"):
JavaScript creates a brand new empty object
It calls the
constructorwith"Toyota"and"Red"this.brandis set to"Toyota"andthis.colouris set to"Red"That object is returned and stored in
car1
Now let's access the properties:
console.log(car1.brand); // Toyota
console.log(car1.colour); // Red
console.log(car2.brand); // Honda
console.log(car2.colour); // Blue
car1 and car2 are completely separate objects. Changing one does not affect the other. But they were both made from the same Car blueprint.
This is the power of OOP, one blueprint, many objects.
Adding Methods to a Class
A method is a function that lives inside a class. It defines something the object can do.
Let's add a describe method to our Car class:
class Car {
constructor(brand, colour) {
this.brand = brand;
this.colour = colour;
}
describe() {
console.log("This car is a " + this.colour + " " + this.brand + ".");
}
}
Now every Car object can call the describe method:
let car1 = new Car("Toyota", "Red");
let car2 = new Car("Honda", "Blue");
car1.describe(); // This car is a Red Toyota.
car2.describe(); // This car is a Blue Honda.
Notice this.brand and this.colour inside the method, when car1 calls describe(), this refers to car1, so it uses car1's own data. When car2 calls it, this refers to car2. Same method, different data, that's the beauty of it.
A More Complete Example: Person Class
Let's build a fuller example with a Person class that has more properties and multiple methods.
class Person {
constructor(name, age, city) {
this.name = name;
this.age = age;
this.city = city;
}
greet() {
console.log("Hi! My name is " + this.name + ".");
}
describe() {
console.log(this.name + " is " + this.age + " years old and lives in " + this.city + ".");
}
}
Creating objects and calling methods:
let person1 = new Person("Rahul", 25, "Mumbai");
let person2 = new Person("Priya", 22, "Delhi");
person1.greet(); // Hi! My name is Rahul.
person1.describe(); // Rahul is 25 years old and lives in Mumbai.
person2.greet(); // Hi! My name is Priya.
person2.describe(); // Priya is 22 years old and lives in Delhi.
We wrote the greet and describe methods once inside the class. But every object we create gets to use them. 100 people, still just two method definitions.
What Is Encapsulation?
Encapsulation sounds like a big word, but the idea is simple:
Keep the data and the actions that work on that data together, in one place.
In our Person class, the data (name, age, city) and the actions that use that data (greet, describe) all live together inside the class. That's encapsulation.
It also means the object manages its own data. You don't need to know exactly how describe() works inside, you just call it and it gives you the result. The details are hidden away inside the object.
Think of a TV remote. You press the volume button and the volume goes up. You don't need to know the circuit diagram, the remote handles it internally. That's encapsulation in everyday life.
This makes your code:
Organised — everything related to a Person is inside the Person class
Safe — the internal workings are not exposed unnecessarily
Easy to use — just call the method, the object handles the rest
Updating Properties After Creation
You can still update an object's properties after it has been created:
let person1 = new Person("Rahul", 25, "Mumbai");
console.log(person1.age); // 25
person1.age = 26;
console.log(person1.age); // 26
You can also write a method inside the class specifically for updating a property:
class Person {
constructor(name, age, city) {
this.name = name;
this.age = age;
this.city = city;
}
birthday() {
this.age = this.age + 1;
console.log("Happy Birthday " + this.name + "! You are now " + this.age + ".");
}
}
let person1 = new Person("Rahul", 25, "Mumbai");
person1.birthday(); // Happy Birthday Rahul! You are now 26.
person1.birthday(); // Happy Birthday Rahul! You are now 27.
Why OOP Makes Code Reusable
Let's say you're building a school app and need 5 student records. Without OOP:
// Without OOP — repetitive and messy
let student1 = { name: "Rahul", age: 20, course: "Math" };
let student2 = { name: "Priya", age: 21, course: "Science" };
let student3 = { name: "Aman", age: 22, course: "History" };
// ...and you'd have to manually write a print function for each one
With OOP:
// With OOP — clean and reusable
class Student {
constructor(name, age, course) {
this.name = name;
this.age = age;
this.course = course;
}
printDetails() {
console.log(this.name + " | Age: " + this.age + " | Course: " + this.course);
}
}
let s1 = new Student("Rahul", 20, "Math");
let s2 = new Student("Priya", 21, "Science");
let s3 = new Student("Aman", 22, "History");
s1.printDetails(); // Rahul | Age: 20 | Course: Math
s2.printDetails(); // Priya | Age: 21 | Course: Science
s3.printDetails(); // Aman | Age: 22 | Course: History
The printDetails method is written once, but works perfectly for every student. Add 50 more students, still just one method definition.
Assignment
Write this program yourself, it brings everything from this blog together.
The Task: Student Class
Step 1: Create the class:
class Student {
constructor(name, age, course) {
this.name = name;
this.age = age;
this.course = course;
}
printDetails() {
console.log("--- Student Details ---");
console.log("Name : " + this.name);
console.log("Age : " + this.age);
console.log("Course : " + this.course);
}
}
Step 2: Create multiple student objects:
let student1 = new Student("Rahul", 20, "Computer Science");
let student2 = new Student("Priya", 21, "Mathematics");
let student3 = new Student("Aman", 19, "Physics");
Step 3: Call the method on each object:
student1.printDetails();
student2.printDetails();
student3.printDetails();
Output:
--- Student Details ---
Name : Rahul
Age : 20
Course : Computer Science
--- Student Details ---
Name : Priya
Age : 21
Course : Mathematics
--- Student Details ---
Name : Aman
Age : 19
Course : Physics
Step 4: Update a property and print again:
student1.age = 21;
student1.course = "Data Science";
student1.printDetails();
Output:
--- Student Details ---
Name : Rahul
Age : 21
Course : Data Science
Bonus: Add a method that updates the course:
class Student {
constructor(name, age, course) {
this.name = name;
this.age = age;
this.course = course;
}
changeCourse(newCourse) {
console.log(this.name + " changed course from " + this.course + " to " + newCourse);
this.course = newCourse;
}
printDetails() {
console.log("Name: " + this.name + " | Age: " + this.age + " | Course: " + this.course);
}
}
let student1 = new Student("Rahul", 20, "Math");
student1.changeCourse("Computer Science");
// Rahul changed course from Math to Computer Science
student1.printDetails();
// Name: Rahul | Age: 20 | Course: Computer Science
Quick Recap
| Concept | What It Means | Example |
|---|---|---|
| Class | Blueprint for creating objects | class Car {} |
| Object | A real instance made from a class | let car1 = new Car(...) |
| Constructor | Sets up initial properties when object is created | constructor(brand, colour) |
this |
Refers to the current object | this.brand = brand |
| Method | A function inside a class | describe() { ... } |
new |
Creates a new object from a class | new Car("Toyota", "Red") |
| Encapsulation | Keeping data and actions together in one place | Everything in the class |
Key Takeaways
A class is a blueprint, it defines the structure and behaviour of objects
An object is a real instance created from that blueprint using
newThe constructor runs automatically when you create a new object and sets its starting values
thisrefers to the specific object that is currently being worked withMethods are functions inside a class that describe what an object can do
Encapsulation means keeping related data and actions bundled together in one place
OOP makes your code reusable, write once, use for as many objects as you need
OOP might feel a little abstract at first, but the more you build with classes, the more natural it becomes. Start small, a Person, a Student, a Car, and before long you'll be using classes everywhere. They are the foundation of almost all large JavaScript applications. Keep practising!

