# 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
    
*   `this`
    
*   Instances
    
*   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:

```javascript
const user = {

    name: "Saurabh",

    age: 22,

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

};
```

Here:

```text
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:

```javascript
const user1 = {
    name: "Saurabh",
    age: 22
};

const user2 = {
    name: "Rahul",
    age: 23
};
```

we can define a class:

```javascript
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.

```javascript
class User {

    constructor(name, age) {

        this.name = name;

        this.age = age;

    }

}
```

Now we can create users:

```javascript
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.

```javascript
const user = new User(
    "Saurabh",
    22
);
```

Conceptually:

```text
User Class
     ↓
    new
     ↓
User Instance
```

* * *

# Understanding `this`

The `this` keyword refers to the object associated with the current method or constructor call.

Example:

```javascript
class User {

    constructor(name) {

        this.name = name;

    }

    greet() {

        console.log(
            `Hello ${this.name}`
        );

    }

}
```

When we create:

```javascript
const user = new User("Saurabh");

user.greet();
```

`this.name` refers to:

```text
user.name
```

* * *

# Adding Methods

Classes can contain methods that define object behavior.

```javascript
class Calculator {

    add(a, b) {

        return a + b;

    }

    multiply(a, b) {

        return a * b;

    }

}
```

Create an instance:

```javascript
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.

```javascript
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:

```javascript
class User {

}
```

### Instance

An object created from the class:

```javascript
const user = new User();
```

Think of it like:

```text
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:

```javascript
class BankAccount {

    #balance = 0;

    deposit(amount) {

        this.#balance += amount;

    }

    getBalance() {

        return this.#balance;

    }

}
```

Now:

```javascript
const account = new BankAccount();

account.deposit(1000);

console.log(
    account.getBalance()
);
```

But this won't work:

```javascript
console.log(account.#balance);
```

because `#balance` is private.

* * *

# Inheritance

Inheritance allows one class to reuse functionality from another class.

Suppose we have:

```javascript
class User {

    constructor(name) {

        this.name = name;

    }

    greet() {

        console.log(
            `Hello ${this.name}`
        );

    }

}
```

We can create another class:

```javascript
class Developer extends User {

}
```

Now:

```javascript
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()`.

```javascript
class Developer extends User {

    constructor(name, language) {

        super(name);

        this.language = language;

    }

}
```

Now:

```javascript
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.

```javascript
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:

```javascript
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:

```text
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.
