Object-Oriented Programming with JavaScript

Object-Oriented Programming (OOP) is a programming paradigm that uses objects and classes to structure code. JavaScript, although originally prototype-based, supports OOP concepts through classes and prototypes. This article explores OOP principles in JavaScript with examples.

Table of Contents

  1. Introduction to OOP
  2. Key Principles of OOP
  3. Encapsulation
  4. Inheritance
  5. Polymorphism
  6. Abstraction
  7. Prototypes in JavaScript
  8. ES6 Classes
  9. Best Practices
  10. FAQs

1. Introduction to OOP

OOP revolves around creating objects that model real-world concepts. Objects have properties (data) and methods (functions). JavaScript allows creating objects using constructors or ES6 classes.

Example: Creating an Object

// Object literal
const car = {
  brand: 'Toyota',
  model: 'Camry',
  drive: function() {
    console.log('Driving the car');
  }
};

// Using a constructor
function Car(brand, model) {
  this.brand = brand;
  this.model = model;
  this.drive = function() {
    console.log('Driving the car');
  };
}

const myCar = new Car('Toyota', 'Camry');

2. Key Principles of OOP

2.1 Abstraction

Abstraction hides complex details and shows only necessary information.

Example: Abstracting Car Details

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

  drive() {
    console.log('Driving');
  }
}

const car = new Car('Toyota', 'Camry');
// Car details abstracted

2.2 Encapsulation

Encapsulation bundles data and methods into a single unit, controlling access to data.

Example: Encapsulating Car Data

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

  get brand() {
    return this._brand;
  }

  set brand(value) {
    this._brand = value;
  }
}

const car = new Car('Toyota', 'Camry');
console.log(car.brand); // 'Toyota'

2.3 Inheritance

Inheritance allows creating a new class (subclass) from an existing class (superclass), inheriting properties and methods.

Example: Inheriting from a Superclass

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

  displayType() {
    console.log(`Type: ${this.type}`);
  }
}

// Subclass
class Car extends Vehicle {
  constructor(brand, model, type) {
    super(type);
    this.brand = brand;
    this.model = model;
  }
}

const car = new Car('Toyota', 'Camry', 'Sedan');
car.displayType(); // 'Type: Sedan'

2.4 Polymorphism

Polymorphism allows methods to behave differently based on the object they’re called on.

Example: Polymorphic Methods

class Animal {
  speak() {
    console.log('Animal speaks');
  }
}

class Dog extends Animal {
  speak() {
    console.log('Dog barks');
  }
}

class Cat extends Animal {
  speak() {
    console.log('Cat meows');
  }
}

const animal = new Animal();
const dog = new Dog();
const cat = new Cat();

animal.speak(); // 'Animal speaks'
dog.speak();    // 'Dog barks'
cat.speak();    // 'Cat meows'

3. Encapsulation in Depth

Encapsulation in JavaScript can be achieved using private properties (ES6) and getter/setter methods.

Example: Private Properties

class BankAccount {
  #balance;

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

  getBalance() {
    return this.#balance;
  }

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

const account = new BankAccount(1000);
console.log(account.getBalance()); // 1000
account.deposit(500);
console.log(account.getBalance()); // 1500

4. Inheritance in JavaScript

JavaScript supports inheritance through prototypes and ES6 classes.

Example: Prototype Inheritance

function Vehicle(type) {
  this.type = type;
}

Vehicle.prototype.displayType = function() {
  console.log(`Type: ${this.type}`);
};

function Car(brand, model, type) {
  Vehicle.call(this, type);
  this.brand = brand;
  this.model = model;
}

// Inherit Vehicle's prototype
Car.prototype = Object.create(Vehicle.prototype);
Car.prototype.constructor = Car;

const car = new Car('Toyota', 'Camry', 'Sedan');
car.displayType(); // 'Type: Sedan'

5. Polymorphism in JavaScript

JavaScript’s dynamic typing allows for flexible method implementations.

Example: Polymorphic Functions

function printDetails(obj) {
  obj.displayType();
}

const animal = new Animal();
const dog = new Dog();

printDetails(animal); // 'Animal speaks'
printDetails(dog);    // 'Dog barks'

6. Abstraction in JavaScript

Abstraction can be achieved using abstract classes (ES6) and interfaces.

Example: Abstract Class

abstract class Shape {
  constructor(color) {
    this.color = color;
  }

  abstract area();
}

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

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

const circle = new Circle('Red', 5);
console.log(circle.area()); // ~78.54

7. Prototypes in JavaScript

Prototypes are a core concept in JavaScript, allowing for efficient code reuse.

Example: Using Prototypes

function Car() {}

Car.prototype.drive = function() {
  console.log('Driving');
};

const car1 = new Car();
const car2 = new Car();

console.log(car1.drive === car2.drive); // true

8. ES6 Classes

ES6 introduced class syntax, making OOP in JavaScript more readable and maintainable.

Example: ES6 Class

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

  drive() {
    console.log('Driving');
  }
}

const car = new Car('Toyota', 'Camry');
car.drive(); // 'Driving'

9. Best Practices

  1. Use ES6 classes for better readability.
  2. Favor composition over inheritance when possible.
  3. Use private properties to encapsulate data.
  4. Write modular code using modules.

10. Frequently Asked Questions

Q1: What is the difference between prototypal and class-based inheritance?

  • Prototypal inheritance (JavaScript’s original model) uses prototypes to share properties and methods.
  • Class-based inheritance (ES6 classes) uses class and extends keywords, similar to other OOP languages.

Q2: Can I mix prototypal and class-based inheritance?

Yes, ES6 classes are syntactic sugar over prototypes. You can still use prototype methods with classes.

Q3: How do I create private methods in JavaScript?

Use the # symbol before a property or method in ES6 classes.

Q4: What is polymorphism in JavaScript?

Polymorphism allows methods to behave differently based on the object they’re called on.

Q5: Is JavaScript a fully object-oriented language?

Yes, JavaScript supports all OOP principles, though it’s prototype-based rather than class-based.

Conclusion

Object-Oriented Programming in JavaScript allows developers to create modular, maintainable, and scalable code. By leveraging classes, prototypes, and OOP principles, you can build complex applications with ease. Happy coding!

Index
Scroll to Top