Object-Oriented Programming (OOP) in JavaScript
Key Concepts
Object-Oriented Programming (OOP) in JavaScript involves several key concepts:
- Classes and Objects
- Inheritance
- Encapsulation
- Polymorphism
- Abstraction
Classes and Objects
A class is a blueprint for creating objects. An object is an instance of a class. In JavaScript, classes can be defined using the class
keyword.
class Car { constructor(make, model) { this.make = make; this.model = model; } drive() { console.log(Driving a ${this.make} ${this.model}); } } const myCar = new Car('Toyota', 'Camry'); myCar.drive(); // Output: Driving a Toyota Camry
Inheritance
Inheritance allows a class to inherit properties and methods from another class. This promotes code reuse. In JavaScript, inheritance is achieved using the extends
keyword.
class ElectricCar extends Car { constructor(make, model, batteryCapacity) { super(make, model); this.batteryCapacity = batteryCapacity; } charge() { console.log(Charging the ${this.make} ${this.model} with ${this.batteryCapacity} kWh battery); } } const myElectricCar = new ElectricCar('Tesla', 'Model S', 100); myElectricCar.drive(); // Output: Driving a Tesla Model S myElectricCar.charge(); // Output: Charging the Tesla Model S with 100 kWh battery
Encapsulation
Encapsulation is the bundling of data with the methods that operate on that data. It also refers to the restriction of direct access to some of an object's components. In JavaScript, encapsulation can be achieved using closures or the #
(private fields) syntax.
class BankAccount { #balance = 0; deposit(amount) { this.#balance += amount; } withdraw(amount) { if (amount <= this.#balance) { this.#balance -= amount; } else { console.log('Insufficient funds'); } } getBalance() { return this.#balance; } } const account = new BankAccount(); account.deposit(1000); account.withdraw(500); console.log(account.getBalance()); // Output: 500
Polymorphism
Polymorphism allows objects of different classes to be treated as objects of a common superclass. It is often achieved through method overriding. In JavaScript, polymorphism can be implemented using method overriding.
class Animal { makeSound() { console.log('Some generic sound'); } } class Dog extends Animal { makeSound() { console.log('Woof!'); } } class Cat extends Animal { makeSound() { console.log('Meow!'); } } function animalSound(animal) { animal.makeSound(); } const dog = new Dog(); const cat = new Cat(); animalSound(dog); // Output: Woof! animalSound(cat); // Output: Meow!
Abstraction
Abstraction is the process of hiding the internal details and showing only the functionality. In JavaScript, abstraction can be achieved by defining methods in a class that operate on the internal data without exposing the internal state.
class Shape { constructor() { if (new.target === Shape) { throw new Error('Shape is an abstract class and cannot be instantiated directly'); } } draw() { throw new Error('Method draw() must be implemented'); } } class Circle extends Shape { draw() { console.log('Drawing a circle'); } } class Square extends Shape { draw() { console.log('Drawing a square'); } } const circle = new Circle(); circle.draw(); // Output: Drawing a circle const square = new Square(); square.draw(); // Output: Drawing a square
Examples and Analogies
Imagine OOP as building with LEGO blocks:
- Classes and Objects: Think of a LEGO set as a class, and each built model as an object.
- Inheritance: Think of a LEGO set that includes instructions for building a basic model and additional instructions for building more complex models using the basic model as a starting point.
- Encapsulation: Think of a LEGO model where the internal structure (how the pieces fit together) is hidden, and you only see the final appearance.
- Polymorphism: Think of different LEGO sets that can be used to build different models, but all models can be displayed together as part of a collection.
- Abstraction: Think of a LEGO set where the instructions provide high-level steps to build a model without detailing every single piece placement.