Object-Oriented Programming in JavaScript – Classes & Objects
Yesterday, I learned about JavaScript Modules and how import and export help organize code into reusable files.
Today, I started exploring Object-Oriented Programming (OOP) in JavaScript.
OOP is a programming approach where we organize code around objects that contain data and behavior.
I explored:
Objects
Classes
Constructors
Methods
thisInstances
Encapsulation
Inheritance
Let's dive in.
What is Object-Oriented Programming?
Object-Oriented Programming (OOP) is a programming paradigm that organizes software around objects.
An object can contain:
Data → Properties
Behavior → Methods
For example:
const user = {
name: "Saurabh",
age: 22,
greet() {
console.log(`Hello, I'm ${this.name}`);
}
};
Here:
Properties → name, age
Method → greet()
The object represents a user and contains both information and behavior.
What is a Class?
A class is a blueprint for creating objects.
Instead of manually creating multiple similar objects:
const user1 = {
name: "Saurabh",
age: 22
};
const user2 = {
name: "Rahul",
age: 23
};
we can define a class:
class User {
}
Then create objects from it.
Constructor
A constructor is a special method that runs automatically when a new instance of a class is created.
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
Now we can create users:
const user1 = new User("Saurabh", 22);
const user2 = new User("Rahul", 23);
Each object gets its own values.
The new Keyword
The new keyword creates a new instance of a class.
const user = new User(
"Saurabh",
22
);
Conceptually:
User Class
↓
new
↓
User Instance
Understanding this
The this keyword refers to the object associated with the current method or constructor call.
Example:
class User {
constructor(name) {
this.name = name;
}
greet() {
console.log(
`Hello ${this.name}`
);
}
}
When we create:
const user = new User("Saurabh");
user.greet();
this.name refers to:
user.name
Adding Methods
Classes can contain methods that define object behavior.
class Calculator {
add(a, b) {
return a + b;
}
multiply(a, b) {
return a * b;
}
}
Create an instance:
const calculator = new Calculator();
console.log(
calculator.add(10, 20)
);
console.log(
calculator.multiply(5, 4)
);
Methods allow objects to perform actions.
Creating Multiple Instances
One class can create many independent objects.
const user1 = new User(
"Saurabh",
22
);
const user2 = new User(
"Aman",
24
);
const user3 = new User(
"Rahul",
23
);
All three objects follow the same structure but contain different data.
Instance vs Class
The distinction is important.
Class
The blueprint:
class User {
}
Instance
An object created from the class:
const user = new User();
Think of it like:
Blueprint → Class
Actual Building → Instance
Encapsulation
Encapsulation means keeping related data and behavior together while controlling how internal state is accessed or changed.
Modern JavaScript supports private class fields using #.
Example:
class BankAccount {
#balance = 0;
deposit(amount) {
this.#balance += amount;
}
getBalance() {
return this.#balance;
}
}
Now:
const account = new BankAccount();
account.deposit(1000);
console.log(
account.getBalance()
);
But this won't work:
console.log(account.#balance);
because #balance is private.
Inheritance
Inheritance allows one class to reuse functionality from another class.
Suppose we have:
class User {
constructor(name) {
this.name = name;
}
greet() {
console.log(
`Hello ${this.name}`
);
}
}
We can create another class:
class Developer extends User {
}
Now:
const developer =
new Developer("Saurabh");
developer.greet();
The Developer class inherits the greet() method from User.
The super Keyword
A child class can call the parent constructor using super().
class Developer extends User {
constructor(name, language) {
super(name);
this.language = language;
}
}
Now:
const developer =
new Developer(
"Saurabh",
"JavaScript"
);
console.log(
developer.name
);
console.log(
developer.language
);
super(name) calls the parent class constructor.
Method Overriding
A child class can provide its own implementation of a method.
class Developer extends User {
greet() {
console.log(
`I'm ${this.name}, a developer.`
);
}
}
Now the child's greet() method replaces the inherited version for that instance.
This is called method overriding.
OOP Concepts
The four commonly discussed OOP principles are:
1. Encapsulation
Keep data and behavior together and control access to internal state.
2. Abstraction
Expose what is necessary while hiding unnecessary implementation details.
3. Inheritance
Allow one class to reuse functionality from another.
4. Polymorphism
Allow objects to respond differently to the same method or interface.
These concepts are useful when designing larger systems.
JavaScript and Prototypes
One important thing I learned is that JavaScript's class syntax is built on top of prototypes.
For example:
class User {
greet() {
console.log("Hello");
}
}
JavaScript uses the prototype system to share methods between instances.
This allows multiple instances to use the same method without each object needing its own separate copy of that method.
When Should We Use Classes?
Classes can be useful when we have many objects that:
Share the same structure
Share similar behavior
Need their own state
Represent entities in an application
Examples include:
User
Product
Cart
Order
BankAccount
GameCharacter
However, classes aren't required for every JavaScript application.
Functions and objects can often be simpler for smaller pieces of logic.
Best Practices
✔ Keep classes focused on a clear responsibility.
✔ Use meaningful class names.
✔ Initialize required instance state in the constructor.
✔ Use private fields when internal state should not be directly accessed.
✔ Don't use inheritance just because it is available—composition can often be simpler.
✔ Keep methods small and focused.
✔ Understand this before working extensively with classes.
My Biggest Takeaway
Today, I learned how JavaScript can organize complex behavior using Object-Oriented Programming.
The most important concepts for me were:
Class → Constructor → Instance → Methods → this
I also learned how inheritance works using:
extends → super()
And I discovered that JavaScript classes are built on top of the language's prototype system.
This gives me another way to structure larger applications and understand how many real-world JavaScript codebases are organized.
