JavaScript Classes – The Complete Guide

JavaScript classes, introduced in ES6, bring a new way of creating objects and implementing object-oriented programming (OOP) principles in JavaScript. They provide a more straightforward and cleaner syntax for creating and managing objects and their inheritance. This guide will explore everything you need to know about JavaScript classes, including what they are, why they are important, where and how to use them, and when they are most beneficial.

What are JavaScript Classes?

JavaScript classes are blueprints for creating objects. They encapsulate data and functions that operate on that data into a single construct. Classes allow you to define properties and methods, and they support inheritance, making it easier to create and manage complex systems.

Syntax

The basic syntax for defining a class in JavaScript is:

JavaScript
class ClassName {
  constructor(parameter1, parameter2) {
    this.property1 = parameter1;
    this.property2 = parameter2;
  }

  method1() {
    // method code
  }

  method2() {
    // method code
  }
}

Example

JavaScript
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greet() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old! 👋`);
  }
}

const john = new Person('John', 30);
john.greet(); // Output: Hello, my name is John and I am 30 years old! 👋

In this example, the Person class has a constructor to initialize the name and age properties and a greet method to display a greeting message.

Why Use JavaScript Classes?

Classes offer several benefits:

  1. Encapsulation: Classes bundle data (properties) and functions (methods) together.
  2. Inheritance: Classes support inheritance, allowing you to create new classes based on existing ones.
  3. Code Reusability: Classes promote reusability by allowing you to create reusable components.
  4. Cleaner Syntax: Classes provide a cleaner and more readable syntax for creating objects.

Encapsulation Example

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

  displayInfo() {
    console.log(`This car is a ${this.brand} ${this.model}. 🚗`);
  }
}

const myCar = new Car('Toyota', 'Corolla');
myCar.displayInfo(); // Output: This car is a Toyota Corolla. 🚗

Where to Use JavaScript Classes?

JavaScript classes can be used in various scenarios to simplify and organize code:

  1. Creating Objects: Use classes to create and manage objects with shared properties and methods.
  2. Inheritance: Use classes to implement inheritance, allowing new classes to extend existing ones.
  3. Encapsulating Functionality: Use classes to encapsulate functionality and create reusable components.

Creating Objects Example

JavaScript
class Dog {
  constructor(name, breed) {
    this.name = name;
    this.breed = breed;
  }

  bark() {
    console.log(`${this.name} says: Woof! 🐶`);
  }
}

const myDog = new Dog('Buddy', 'Golden Retriever');
myDog.bark(); // Output: Buddy says: Woof! 🐶

Inheritance Example

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

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

class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }

  speak() {
    console.log(`${this.name} barks. 🐶`);
  }
}

const myPet = new Dog('Rex', 'German Shepherd');
myPet.speak(); // Output: Rex barks. 🐶

Encapsulating Functionality Example

JavaScript
class Calculator {
  add(a, b) {
    return a + b;
  }

  subtract(a, b) {
    return a - b;
  }
}

const calc = new Calculator();
console.log(calc.add(5, 3)); // Output: 8
console.log(calc.subtract(5, 3)); // Output: 2

How to Use JavaScript Classes?

Define a class with a constructor and methods. Create instances of the class using the new keyword.

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

  displayInfo() {
    console.log(`Username: ${this.username}, Email: ${this.email}`);
  }
}

const user1 = new User('john_doe', 'john@example.com');
user1.displayInfo(); // Output: Username: john_doe, Email: john@example.com

Inheritance

Extend a class using the extends keyword and call the parent class’s constructor with super.

JavaScript
class Employee extends User {
  constructor(username, email, position) {
    super(username, email);
    this.position = position;
  }

  displayInfo() {
    console.log(`Username: ${this.username}, Email: ${this.email}, Position: ${this.position}`);
  }
}

const emp1 = new Employee('jane_doe', 'jane@example.com', 'Manager');
emp1.displayInfo(); // Output: Username: jane_doe, Email: jane@example.com, Position: Manager

Static Methods

Define static methods using the static keyword. These methods can be called on the class itself, not on instances.

JavaScript
class MathUtils {
  static add(a, b) {
    return a + b;
  }

  static subtract(a, b) {
    return a - b;
  }
}

console.log(MathUtils.add(10, 5)); // Output: 15
console.log(MathUtils.subtract(10, 5)); // Output: 5

When to Use JavaScript Classes?

When Creating Complex Objects

Use classes when you need to create complex objects with multiple properties and methods.

JavaScript
class Book {
  constructor(title, author, pages) {
    this.title = title;
    this.author = author;
    this.pages = pages;
  }

  read() {
    console.log(`Reading "${this.title}" by ${this.author}. 📖`);
  }
}

const myBook = new Book('1984', 'George Orwell', 328);
myBook.read(); // Output: Reading "1984" by George Orwell. 📖

When Implementing Inheritance

Use classes to implement inheritance, allowing you to create new classes based on existing ones.

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

  move() {
    console.log(`The ${this.type} moves on ${this.wheels} wheels. 🚴`);
  }
}

class Bicycle extends Vehicle {
  constructor(type, wheels, gears) {
    super(type, wheels);
    this.gears = gears;
  }

  move() {
    console.log(`The ${this.type} moves on ${this.wheels} wheels with ${this.gears} gears. 🚴`);
  }
}

const myBike = new Bicycle('bicycle', 2, 18);
myBike.move(); // Output: The bicycle moves on 2 wheels with 18 gears. 🚴

When Encapsulating Functionality

Use classes to encapsulate functionality, creating reusable components.

JavaScript
class Timer {
  start() {
    console.log('Timer started ⏱️');
  }

  stop() {
    console.log('Timer stopped ⏲️');
  }
}

const myTimer = new Timer();
myTimer.start(); // Output: Timer started ⏱️
setTimeout(() => myTimer.stop(), 2000); // Output after 2 seconds: Timer stopped ⏲️

Private Fields and Methods

Use private fields and methods to encapsulate data and logic within a class. Private fields are prefixed with #.

JavaScript
class BankAccount {
  #balance;

  constructor(owner, balance) {
    this.owner = owner;
    this.#balance = balance;
  }

  deposit(amount) {
    this.#balance += amount;
    console.log(`Deposited ${amount}. New balance: ${this.#balance} 💰`);
  }

  withdraw(amount) {
    if (amount <= this.#balance) {
      this.#balance -= amount;
      console.log(`Withdrew ${amount}. New balance: ${this.#balance} 💸`);
    } else {
      console.log('Insufficient funds ❌');
    }
  }

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

const account = new BankAccount('Alice', 1000);
account.deposit(500); // Output: Deposited 500. New balance: 1500 💰
account.withdraw(200); // Output: Withdrew 200. New balance: 1300 💸
console.log(account.getBalance()); // Output: 1300

Getters and Setters

Use getters and setters to control access to properties.

JavaScript
class Rectangle {
  constructor(width, height) {
    this._width =

 width;
    this._height = height;
  }

  get area() {
    return this._width * this._height;
  }

  set width(value) {
    this._width = value;
  }

  set height(value) {
    this._height = value;
  }
}

const rect = new Rectangle(10, 5);
console.log(rect.area); // Output: 50
rect.width = 20;
console.log(rect.area); // Output: 100

Abstract Classes

Abstract classes cannot be instantiated directly. They are designed to be extended by other classes.

JavaScript
class Shape {
  constructor(name) {
    if (new.target === Shape) {
      throw new TypeError("Cannot construct Shape instances directly");
    }
    this.name = name;
  }

  area() {
    throw new Error('Method "area" must be implemented');
  }
}

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

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

const myCircle = new Circle(5);
console.log(`The area of the ${myCircle.name} is ${myCircle.area()} 🟢`); // Output: The area of the Circle is 78.53981633974483 🟢

Summary

JavaScript classes provide a robust and clean way to implement object-oriented programming. They allow for encapsulation, inheritance, and code reusability, making it easier to manage and maintain complex systems. Whether you’re creating objects, implementing inheritance, or encapsulating functionality, understanding how to use classes effectively can greatly enhance your JavaScript programming skills. Practice using classes in various scenarios to see their full potential and improve your code quality.

Leave a Reply