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
- Introduction to OOP
- Key Principles of OOP
- Encapsulation
- Inheritance
- Polymorphism
- Abstraction
- Prototypes in JavaScript
- ES6 Classes
- Best Practices
- 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
- Use ES6 classes for better readability.
- Favor composition over inheritance when possible.
- Use private properties to encapsulate data.
- 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!