Explaining the Concept of a Class in ES6 and the Distinction Between a Function Constructor

February 9, 2023

☕️ Support Us
Your support will help us to continue to provide quality content.👉 Buy Me a Coffee

ES6 class

In JavaScript, before the introduction of the class syntax in ECMAScript 6 (ES6), objects were created through function constructors and then instantiated through the new keyword. The class concept was introduced in ES6 as a syntactic sugar for JavaScript classes, which essentially simulates the behavior of a class through prototypal inheritance. Here's an example of creating a Car class in ES6:

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

  drive() {
    console.log(`Driving a ${this.brand} ${this.model}`);
  }
}

const myCar = new Car("Tesla", "Model 3");
myCar.drive(); // Driving a Tesla Model 3

This example can be written in ES5 using functions, as follows:

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

Car.prototype.drive = function () {
  console.log(`Driving a ${this.brand} ${this.model}`);
};

const myCar = new Car("Tesla", "Model 3");
myCar.drive(); // Driving a Tesla Model 3

Notice that the drive() method is not encapsulated inside the Car class in the ES6 version, but is assigned to the Car prototype instead.

Difference Between ES6 Class and ES5 Function Constructor

There are several main differences between ES6 class and ES5 function constructor:

  1. Hoisting: Function constructor are hoisted, but class declarations cannot be used before they are declared.

    var newClass = new MyClass(); // Uncaught ReferenceError: MyClass is not defined is not defined
    
    class MyClass {}
    
  2. The new keyword: The constructor created by a function can be executed as a general function if not instantiated through new. But a class constructor must use new to create an instance; otherwise, it will throw an error.

    class Animal {}
    const a = Animal(); // Uncaught TypeError: Class constructor Animal cannot be invoked without 'new'
    

Common Methods of Class

Inheritance

In ES6, inheritance is achieved through the extends keyword. Here's an example of creating a Dog subclass that extends the Animal class:

Suppose there is a parent class Animal

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

  eat() {
    console.log(`${this.name} eat food.`);
  }

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

class Dog extends Animal {
  constructor(name) {
    super(name);
  }

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

In this example, the Dog class inherits all the properties and methods of the Animal class and can also override the speak() method.

static Method

Static methods are methods that belong to a class, not an instance of a class, and can be called on the class itself. Unlike regular methods, they cannot be accessed from an instance of a class. The static keyword is used to define a static method on a class.

class Circle {
  constructor(radius) {
    this.radius = radius;
  }

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

console.log(Circle.area(5)); // 78.53981633974483

In the above example, the Circle class has a static method area() that calculates the area of the circle. The area() method is called on the Circle class itself, not on an instance of the Circle class.

Private Fields

In ES6, you can define private fields in a class by prefixing the field name with the # symbol. Private fields can only be accessed within the class, not from outside the class.

class BankAccount {
  #balance = 0;

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

  withdraw(amount) {
    if (this.#balance >= amount) {
      this.#balance -= amount;
      return true;
    } else {
      return false;
    }
  }

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

const account = new BankAccount();
account.deposit(100);
console.log(account.balance); // 100
account.withdraw(50);
console.log(account.balance); // 50

In the above example, the BankAccount class has a private field #balance that is initialized to 0. The deposit() and withdraw() methods modify the balance, and the balance getter returns the current balance. The #balance field can only be accessed from within the class, not from outside the class.

☕️ Support Us
Your support will help us to continue to provide quality content.👉 Buy Me a Coffee