Object-Oriented Programming in JavaScript with Examples [Updated 2024]
Tags: codenewbie, frontend, computerscience, javascript
Published: 2024-01-03 23:02:01

**_O_**bject-Oriented Programming (OOP) in JavaScript is a paradigm centered around objects rather than functions. Unlike procedural programming, which structures programs as sequences of steps or logic, OOP models complex systems as interactive objects. This guide delves into the core principles of OOP in JavaScript, with some coding examples.

---

### Fundamentals of OOP in JavaScript

#### 1. Objects and Classes
In JavaScript, an object is a standalone entity, with properties and type. 

**Code Example - Creating an Object**:
```javascript
let dog = {
  breed: 'Labrador',
  color: 'black',
  bark() {
    console.log('Woof!');
  }
};
dog.bark(); // Woof!
```

Classes, introduced in ES6, are a template for creating objects.

**Code Example - Defining a Class**:
```javascript
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

let animal = new Animal('Dog');
animal.speak(); // Dog makes a noise.
```

#### 2. Encapsulation
Encapsulation means that the internal representation of an object is hidden from the outside.

**Code Example - Encapsulation**:
```javascript
class Car {
  constructor(brand) {
    this._brand = brand;
  }

  get brand() {
    return this._brand;
  }

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

let myCar = new Car('Ford');
console.log(myCar.brand); // Ford
myCar.brand = 'BMW';
console.log(myCar.brand); // BMW
```

#### 3. Inheritance
Inheritance allows a class to inherit properties and methods from another class.

**Code Example - Inheritance**:
```javascript
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

class Dog extends Animal {
  speak() {
    console.log(`${this.name} barks.`);
  }
}

let d = new Dog('Mitzie');
d.speak(); // Mitzie barks.
```

#### 4. Polymorphism
Polymorphism allows objects of different classes to be treated as objects of a common superclass.

**Code Example - Polymorphism**:
```javascript
class Animal {
  speak() {
    console.log('Animal speaks');
  }
}

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

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

function makeAnimalSpeak(animal) {
  animal.speak();
}

makeAnimalSpeak(new Cat()); // Meow
makeAnimalSpeak(new Dog()); // Woof
```

#### 5. Abstraction
Abstraction involves creating simple models representing complex real-world objects.

**Code Example - Abstraction**:
```javascript
class Vehicle {
  startEngine() {
    console.log('Engine started');
  }

  stopEngine() {
    console.log('Engine stopped');
  }
}

class Car extends Vehicle {
  startEngine() {
    console.log('Car engine started');
  }
}

let myCar = new Car();
myCar.startEngine(); // Car engine started
```

---

### Advanced OOP Concepts in JavaScript

#### 6. Constructors and the `new` Keyword
Constructors are special functions that create and initialize objects.

**Code Example - Constructor**:
```javascript
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

let person = new Person('Alice', 25);
console.log(person); // Person { name: 'Alice', age: 25 }
```

#### 7. Methods - Instance, Static, and Prototype Methods
Methods in JavaScript classes can be instance, static, or prototype methods.

**Code Example - Different Methods**:
```javascript
class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  // Instance method
  getArea() {
    return this.width * this.height;
  }

  // Static method
  static compareArea(rect1, rect2) {
    return rect1.getArea() - rect2.getArea();
  }
}

let rect1 = new Rectangle(5, 8);
let rect2 = new Rectangle(6, 7);
console.log(Rectangle.compareArea(rect1, rect2)); // -2
```

#### 8. Getters and Setters
Getters and setters allow you to define Object Accessors (Computed Properties).

**Code Example

 - Getters and Setters**:
```javascript
class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  }

  set fullName(name) {
    [this.firstName, this.lastName] = name.split(' ');
  }
}

let person = new Person('John', 'Doe');
console.log(person.fullName); // John Doe
person.fullName = 'Jane Smith';
console.log(person.fullName); // Jane Smith
```

#### 9. Inheritance with `extends` and `super`
The `extends` keyword is used in class declarations to create a class as a child of another class.

**Code Example - Inheritance with `extends` and `super`**:
```javascript
class Shape {
  constructor(name) {
    this.name = name;
  }

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

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

let myCircle = new Circle(5);
myCircle.move(); // Circle moved
```

---

### Object-Oriented vs. Functional Programming in JavaScript

#### Differences Between OOP and Functional Programming
- **State and Immutability**: OOP handles state within objects, which can change over time. In contrast, functional programming prefers immutable data structures and pure functions without side effects.
- **Methodology**: OOP is about modeling real-world entities using objects and classes, whereas functional programming focuses on the computation process and avoids changing state.
- **Code Reusability**: In OOP, reusability comes through inheritance and polymorphism. Functional programming achieves reusability through functions and higher-order functions.

#### When to Use OOP or Functional Programming
- **Use OOP when**:
  - You're dealing with a complex system with clearly defined types and relationships.
  - Your application's state changes frequently and needs to be managed cohesively.
  - You prefer a modular and structured approach to organizing code.

- **Use Functional Programming when**:
  - You need a robust system with operations that don't depend on or alter the state.
  - Your focus is on the flow of data and transformations applied to it.
  - You aim for code that's easy to test and reason about due to its immutability and purity.

---

**Conclusion:**
Object-oriented programming in JavaScript offers a powerful way to structure and organize code, especially for complex applications. While it differs from functional programming, both paradigms have unique strengths and can even be combined in a single project for different aspects of the application. Understanding both OOP and functional programming will make you a more versatile and effective JavaScript developer.

I hope this guide has helped deepen your understanding of OOP in JavaScript. If you have any questions, experiences, or insights to share, feel free to comment below!