Skip to main content

Command Palette

Search for a command to run...

Object-Oriented Programming (OOP) in JavaScript

Updated
12 min readView as Markdown
Object-Oriented Programming (OOP) in JavaScript
M
Software Engineer exploring software, networking, and systems. I document what I learn, share practical insights, and learn from the community.

If you've ever created a JavaScript object like this:

const student = {
  name: "Maaz",
  age: 20
};

you've already used one of the basic building blocks of Object-Oriented Programming (OOP).

But as applications grow, we often need hundreds of similar objects: students, users, products, cars, orders, and more.

Instead of repeatedly defining the same structure, OOP gives us a better idea:

Create a blueprint once, then use that blueprint to create as many objects as you need.

In this beginner-friendly guide, we'll understand OOP in JavaScript from the ground up using simple examples and visual representations.


What Is Object-Oriented Programming?

Object-Oriented Programming (OOP) is a way of organizing code around objects.

An object usually contains two things:

  • Properties → information/data

  • Methods → actions/behavior

For example, think about a Car.

CAR
├── Properties
│   ├── brand
│   ├── model
│   └── color
│
└── Methods
    ├── start()
    ├── drive()
    └── stop()

So instead of keeping a car's data in one place and its related functions somewhere else, OOP lets us organize them together.

A simple mental model is:

             OBJECT
        ┌─────────────┐
        │    DATA     │
        │ brand       │
        │ model       │
        ├─────────────┤
        │  BEHAVIOR   │
        │ start()     │
        │ drive()     │
        └─────────────┘

That's the basic idea behind OOP.


The Best Analogy: Blueprint → Objects

Imagine an architect creates a house blueprint.

The blueprint might describe:

HOUSE BLUEPRINT
├── rooms
├── doors
├── windows
└── methods/behavior

The blueprint itself isn't a house.

It is a plan for creating houses.

From that blueprint, we can build many houses:

                    BLUEPRINT
                  ┌─────────────┐
                  │ House       │
                  │ rooms       │
                  │ doors       │
                  │ windows     │
                  └──────┬──────┘
                         │
             ┌───────────┼───────────┐
             ↓           ↓           ↓
          House 1     House 2     House 3
          3 rooms     5 rooms     4 rooms
          White       Blue        Gray

JavaScript classes work in a very similar way.

Class = Blueprint Object = Actual thing created from the blueprint

This single idea makes most of the beginner-level OOP syntax much easier to understand.


What Is a Class in JavaScript?

A class is a blueprint for creating objects.

JavaScript provides the class keyword:

class Car {

}

We can define what every car should contain:

class Car {
  constructor(brand, model) {
    this.brand = brand;
    this.model = model;
  }

  drive() {
    console.log(`${this.brand} ${this.model} is driving.`);
  }
}

Think of this class as the blueprint:

                 Car CLASS
              ┌──────────────┐
              │ brand        │
              │ model        │
              │              │
              │ drive()      │
              └──────┬───────┘
                     │
              creates objects
                     │
          ┌──────────┼──────────┐
          ↓          ↓          ↓
        Car 1      Car 2      Car 3
       Toyota      Honda       BMW
       Corolla     Civic        X5

The class defines the structure and behavior.

The objects contain the actual values.


Creating Objects From a Class

A class is only a blueprint. We still need to create objects from it.

JavaScript uses the new keyword:

const car1 = new Car("Toyota", "Corolla");
const car2 = new Car("Honda", "Civic");
const car3 = new Car("BMW", "X5");

Now we have three separate objects:

             Car Class
                │
               new
                │
     ┌──────────┼──────────┐
     ↓          ↓          ↓
   car1       car2       car3
 Toyota      Honda       BMW
 Corolla     Civic        X5

All three objects follow the same blueprint, but their data is different.

This is where code reusability becomes powerful.

Instead of designing the structure three times, we define it once and reuse it.


What Does the new Keyword Do?

When you write:

const car = new Car("Toyota", "Corolla");

you're essentially saying:

"Create a new object using the Car class."

The basic flow is:

new Car(...)
     │
     ↓
Create a new object
     │
     ↓
Initialize its data
     │
     ↓
Return the object

That's why you'll commonly see:

const user = new User();
const product = new Product();
const student = new Student();

The Constructor Method

Now let's understand this:

constructor(name, age) {
  this.name = name;
  this.age = age;
}

A constructor is a special method that runs automatically when we create a new object.

For example:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

When we write:

const person = new Person("Maaz", 20);

the constructor runs automatically.

Think of it like this:

new Person("Maaz", 20)
          │
          ↓
     constructor()
          │
          ├── name → "Maaz"
          └── age  → 20
          │
          ↓
      Person Object

The constructor's main job is usually to initialize the new object's properties.


Understanding this

You will see this everywhere in JavaScript classes.

Consider:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

Here:

this.name

means:

"The name property of this particular object."

For example:

const person1 = new Person("Maaz", 20);
const person2 = new Person("Ali", 21);

The result can be imagined as:

person1
┌──────────────┐
│ name: Maaz   │
│ age: 20      │
└──────────────┘

person2
┌──────────────┐
│ name: Ali    │
│ age: 21      │
└──────────────┘

When the constructor creates person1, this refers to person1.

When it creates person2, this refers to person2.

For now, remember:

this refers to the current object when working with an object instance.


Methods: Giving Objects Behavior

Objects don't just store information. They can also perform actions.

These actions are called methods.

For example:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  introduce() {
    console.log(`Hi, I'm ${this.name}.`);
  }
}

Create an object:

const person = new Person("Maaz", 20);

Call its method:

person.introduce();

Output:

Hi, I'm Maaz.

So now our object contains:

Person Object
├── name
├── age
└── introduce()

This is an important OOP idea:

Objects can contain both data and behavior.


A Practical Example: Student Class

Let's build something you might actually use in an application.

Suppose we're creating a university system.

Every student has:

  • name

  • age

And every student should be able to display their details.

class Student {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  displayDetails() {
    console.log(`Name: ${this.name}, Age: ${this.age}`);
  }
}

Now create multiple students:

const student1 = new Student("Maaz", 20);
const student2 = new Student("Ali", 21);
const student3 = new Student("Ahmed", 22);

And use them:

student1.displayDetails();
student2.displayDetails();
student3.displayDetails();

Output:

Name: Maaz, Age: 20
Name: Ali, Age: 21
Name: Ahmed, Age: 22

Look at what happened.

We wrote the structure once:

Student Class
     │
     ├── name
     ├── age
     └── displayDetails()

Then created many objects:

             Student Class
                  │
        ┌─────────┼─────────┐
        ↓         ↓         ↓
     student1  student2  student3
       Maaz       Ali      Ahmed
        20        21         22

That's reusability in action.


Basic Idea of Encapsulation

Another important OOP concept is encapsulation.

Don't worry about the complicated definition.

At a beginner level, think of encapsulation as:

Keeping related data and the operations that work with that data together, while controlling how that data is changed.

Consider a bank account.

class BankAccount {
  constructor(balance) {
    this.balance = balance;
  }

  deposit(amount) {
    this.balance += amount;
  }

  withdraw(amount) {
    if (amount > this.balance) {
      console.log("Insufficient balance.");
      return;
    }

    this.balance -= amount;
  }
}

Now:

const account = new BankAccount(1000);

account.deposit(500);
account.withdraw(200);

The account's data and related operations are grouped together:

             BankAccount
          ┌───────────────┐
          │ balance       │
          ├───────────────┤
          │ deposit()     │
          │ withdraw()    │
          └───────────────┘

This is the basic idea.

JavaScript has more advanced ways to implement encapsulation, such as private fields (#), getters, setters, and modules. Those can be learned later.


Class vs Object: Never Confuse These

This is one of the most common beginner mistakes.

Class

A class is the blueprint.

class Student {
  // blueprint
}

Object

An object is an instance created from that blueprint.

const student = new Student();

Visualize it like this:

CLASS
(Blueprint)
   │
   │ new
   ↓
OBJECT
(Actual instance)

Or with multiple objects:

                 Student
                  CLASS
               (Blueprint)
                    │
             ┌──────┼──────┐
             ↓      ↓      ↓
          Object  Object  Object
          Maaz     Ali    Ahmed

Once this distinction is clear, classes become much less intimidating.


Why Use OOP?

Imagine you're building a large application.

You might have:

Application
├── Users
├── Products
├── Orders
├── Payments
└── Notifications

Each entity has its own data and behavior.

For example:

User
├── name
├── email
├── login()
└── logout()

Product
├── name
├── price
└── updatePrice()

Order
├── items
├── total
└── calculateTotal()

OOP gives you a structured way to model these entities.

The biggest beginner-friendly benefits are:

  • Reusability — define a structure once and reuse it.

  • Organization — keep related data and behavior together.

  • Maintainability — larger codebases can become easier to manage.

  • Modeling — real-world entities can be represented naturally.


A Complete Example

Here's everything together:

class Student {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  displayDetails() {
    console.log(
      `Student: ${this.name}, Age: ${this.age}`
    );
  }
}

const student1 = new Student("Maaz", 20);
const student2 = new Student("Ali", 21);

student1.displayDetails();
student2.displayDetails();

The complete mental flow is:

class Student
      │
      │ defines
      ↓
properties + methods
      │
      │ new Student()
      ↓
┌───────────────┐
│ student1      │
│ name: Maaz    │
│ age: 20       │
└───────────────┘

┌───────────────┐
│ student2      │
│ name: Ali     │
│ age: 21       │
└───────────────┘

You define the blueprint once and create as many instances as your application needs.


Your Practice Challenge

Now try building the Student class yourself.

Requirements

Create a class called Student.

It should have:

  • name

  • age

  • displayDetails() method

Then create at least two student objects.

Your goal should be to reach something like:

Student Class
     │
     ├── name
     ├── age
     └── displayDetails()
            │
      ┌─────┴─────┐
      ↓           ↓
   Student 1   Student 2
     Maaz         Ali
      20          21

Try it before looking at the complete example above. Writing it yourself is where the concept really sticks.


The Key Idea

If you're new to OOP, don't try to memorize everything at once.

Remember this:

CLASS
  ↓
Blueprint

new
  ↓
Creates an object

CONSTRUCTOR
  ↓
Initializes the object

PROPERTIES
  ↓
Store data

METHODS
  ↓
Define behavior

OBJECT
  ↓
Actual instance created from the class

Or, in one picture:

                 CLASS
              (Blueprint)
                   │
                  new
                   ↓
              ┌─────────┐
              │ OBJECT  │
              ├─────────┤
              │ Data    │
              │         │
              │ Methods │
              └─────────┘

That's the foundation of OOP in JavaScript.


The Core Insight

Object-Oriented Programming isn't about memorizing complicated terminology.

At its core, it's about organizing related data and behavior into objects and creating reusable structures for those objects.

A JavaScript class gives you a blueprint:

class Student {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  displayDetails() {
    console.log(`${this.name} is ${this.age} years old.`);
  }
}

Then new creates actual objects from that blueprint:

const student1 = new Student("Maaz", 20);
const student2 = new Student("Ali", 21);

So whenever you see:

class → constructor → new → object → method

think:

Blueprint
   ↓
Build
   ↓
Object
   ↓
Data + Behavior

Once this becomes natural, concepts like inheritance, polymorphism, abstraction, private fields, getters, and setters become much easier to learn.

The goal isn't to write more classes.

The goal is to use the right structure to make your JavaScript applications clearer, more reusable, and easier to maintain.


Bonus: What Are JavaScript Classes Really?

JavaScript Classes vs. C++/Java Classes

If you've worked with C++ or Java, there's an important difference to understand.

When you write:

class Student {
  constructor(name) {
    this.name = name;
  }
}

JavaScript's class syntax may look very similar to a class in Java or C++.

But JavaScript's object model works differently.

Java and C++ are traditionally class-based languages. Classes are a fundamental part of how objects and inheritance are structured.

JavaScript, however, is fundamentally prototype-based.

Java / C++
     │
     ↓
   CLASS
     │
     ↓
  OBJECTS


JavaScript
     │
     ↓
 PROTOTYPE SYSTEM
     │
     ↓
 class syntax
 (cleaner interface)
     │
     ↓
  OBJECTS

So don't assume:

class in JavaScript = exactly the same kind of class as in Java or C++.

The syntax looks familiar because JavaScript's class syntax was designed to provide a more familiar and cleaner way to work with objects and inheritance.

Underneath, JavaScript still uses prototypes.

Why Does This Matter?

For everyday beginner-level JavaScript, you can comfortably write:

class Student {
  constructor(name) {
    this.name = name;
  }

  introduce() {
    console.log(`Hi, I'm ${this.name}`);
  }
}

You don't need to think about prototypes every time you create a class.

But as you progress into topics such as:

  • inheritance

  • extends

  • super

  • prototypes

  • method lookup

  • Object.getPrototypeOf()

understanding this distinction becomes very useful.

So remember this simple rule:

JavaScript looks class-based on the surface, but its object model is prototype-based underneath.

That is one of the most important differences between JavaScript's class syntax and the traditional class model you'll encounter in languages such as Java and C++.

4 views

More from this blog