Explaining the Concept of a Class in ES6 and the Distinction Between a Function Constructor
February 9, 2023
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:
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 {}
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.