DEV Community

Cover image for Exploring Object-Oriented Programming (OOP) in JavaScript
arjun
arjun

Posted on

Exploring Object-Oriented Programming (OOP) in JavaScript

Exploring Object-Oriented Programming (OOP) in JavaScript

Date: December 17, 2024

Object-Oriented Programming (OOP) is a paradigm that uses objects to model real-world entities. JavaScript, being a versatile programming language, provides robust support for OOP through its prototypes, ES6 classes, and modern enhancements. Today, we'll dive deep into the principles and features of OOP in JavaScript.


Core Concepts of OOP in JavaScript

1. Objects

Objects are the building blocks of OOP. In JavaScript, an object is a collection of key-value pairs.

Example: Creating Objects

const car = {
  brand: "Toyota",
  model: "Corolla",
  start() {
    return `${this.brand} ${this.model} is starting.`;
  }
};

console.log(car.start()); // Output: Toyota Corolla is starting.
Enter fullscreen mode Exit fullscreen mode

2. Classes

Classes are blueprints for creating objects. They encapsulate data and behavior. JavaScript introduced the class keyword in ES6.

Example: Creating a Class

class Animal {
  constructor(name, species) {
    this.name = name;
    this.species = species;
  }

  makeSound() {
    return `${this.name} is making a sound.`;
  }
}

const dog = new Animal("Buddy", "Dog");
console.log(dog.makeSound()); // Output: Buddy is making a sound.
Enter fullscreen mode Exit fullscreen mode

3. Encapsulation

Encapsulation means bundling data and methods together while restricting direct access to some components. JavaScript achieves this using public, private, and protected members.

Private Fields

Private fields are denoted by a # prefix and are accessible only within the class.

Example: Private Fields

class BankAccount {
  #balance;

  constructor(initialBalance) {
    this.#balance = initialBalance;
  }

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

  getBalance() {
    return this.#balance;
  }
}

const account = new BankAccount(100);
account.deposit(50);
console.log(account.getBalance()); // Output: 150
// console.log(account.#balance); // Error: Private field '#balance' must be declared in an enclosing class
Enter fullscreen mode Exit fullscreen mode

4. Inheritance

Inheritance allows one class to inherit properties and methods from another class using the extends keyword.

Example: Inheritance

class Vehicle {
  constructor(brand) {
    this.brand = brand;
  }

  start() {
    return `${this.brand} vehicle is starting.`;
  }
}

class Car extends Vehicle {
  constructor(brand, model) {
    super(brand); // Calls the parent class constructor
    this.model = model;
  }

  display() {
    return `${this.brand} ${this.model} is ready to go.`;
  }
}

const myCar = new Car("Tesla", "Model S");
console.log(myCar.display()); // Output: Tesla Model S is ready to go.
Enter fullscreen mode Exit fullscreen mode

5. Polymorphism

Polymorphism allows a subclass to override a method from its parent class to provide a specific implementation.

Example: Method Overriding

class Shape {
  area() {
    return "Area is not defined.";
  }
}

class Circle extends Shape {
  constructor(radius) {
    super();
    this.radius = radius;
  }

  area() {
    return Math.PI * this.radius ** 2;
  }
}

const circle = new Circle(5);
console.log(circle.area()); // Output: 78.53981633974483
Enter fullscreen mode Exit fullscreen mode

6. Abstraction

Abstraction focuses on exposing only essential details while hiding implementation complexities. While JavaScript doesn't have abstract classes natively, you can simulate them.

Example: Simulating Abstraction

class Animal {
  constructor(name) {
    if (this.constructor === Animal) {
      throw new Error("Abstract class cannot be instantiated directly.");
    }
    this.name = name;
  }

  makeSound() {
    throw new Error("Abstract method must be implemented.");
  }
}

class Dog extends Animal {
  makeSound() {
    return "Bark!";
  }
}

const dog = new Dog("Buddy");
console.log(dog.makeSound()); // Output: Bark!
// const animal = new Animal("Some Animal"); // Error: Abstract class cannot be instantiated directly.
Enter fullscreen mode Exit fullscreen mode

7. Prototypes and Prototype Chain

JavaScript is a prototype-based language. Every object has an internal link to another object called its prototype.

Example: Prototype Chain

function Person(name) {
  this.name = name;
}

Person.prototype.greet = function () {
  return `Hello, my name is ${this.name}.`;
};

const person1 = new Person("Alice");
console.log(person1.greet()); // Output: Hello, my name is Alice.
Enter fullscreen mode Exit fullscreen mode

8. Object Composition vs. Inheritance

Instead of using inheritance, you can compose objects by combining functionalities. This approach avoids the complexities of deep inheritance hierarchies.

Example: Composition

const canDrive = {
  drive() {
    return "Driving a vehicle.";
  }
};

const canFly = {
  fly() {
    return "Flying an aircraft.";
  }
};

const pilot = Object.assign({}, canDrive, canFly);
console.log(pilot.drive()); // Output: Driving a vehicle.
console.log(pilot.fly());   // Output: Flying an aircraft.
Enter fullscreen mode Exit fullscreen mode

Key Principles of OOP

  1. DRY (Don't Repeat Yourself): Reuse code through classes and inheritance.
  2. SOLID Principles: Follow best practices for writing scalable and maintainable OOP code.

Real-World Example: User Management System

Step 1: Define a Base Class

class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }

  login() {
    return `${this.name} has logged in.`;
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Extend Functionality

class Admin extends User {
  deleteUser(user) {
    return `${user.name} has been deleted by ${this.name}.`;
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Create Instances

const admin = new Admin("Admin Arjun", "admin@example.com");
const user = new User("Regular Parth", "Parth@example.com");

console.log(admin.login()); // Output: Admin Arjun has logged in.
console.log(admin.deleteUser(user)); // Output: Regular Parth has been deleted by Admin Arjun.
Enter fullscreen mode Exit fullscreen mode

Practice Tasks

  1. Create a class hierarchy for a library management system.
  2. Implement a BankAccount class with private fields for balance and public methods for deposit and withdrawal.
  3. Write a Vehicle class with subclasses like Car and Bike demonstrating polymorphism.

Conclusion

OOP in JavaScript provides a powerful way to write clean, modular, and reusable code. By mastering concepts like classes, inheritance, encapsulation, and polymorphism, you'll be well-equipped to build scalable applications. Keep experimenting and applying these concepts to real-world problems to solidify your understanding!

Tomorrow’s Topic: We’ll explore Asynchronous Programming in JavaScript, diving deep into callbacks, promises, and async/await. Stay tuned!

Top comments (0)