JavaScript is a prototype-based programming language, and each object in JavaScript inherits a hidden prototype property that can be used to extend properties and methods.

ECMAScript 2015 (ES6), for the first time, introduced the concept of classes in JavaScript. In an object-oriented programming language, a class is a template for creating objects with properties and methods of the same kind. However, that is not the case in JavaScript.

JavaScript classes are nothing but just syntactic sugar over existing prototype-based inheritance and constructor functions.

Defining a class

You can define a new class in JavaScript by using the class keyword:

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

    greeting() {
        return `Hey ${this.name} 👋`;
    }
}

The example above declares the User class with two initial properties: name and age. To create a new instance of User, you muse use the new keyword:

const alex = new User('Alex Jones', 32);

console.log(alex.greeting()); // Hey Alex Jones 👋

When a new object is created, the constructor() method is called automatically by the new keyword.

Class expression

Just like arrow functions, classes can also be defined inside another expression. A class expression can be named or named.

Here is an example of unnamed class expression:

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

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

const circle = new Circle(10, 'Blue');

console.log(circle.area()); // 314.1592653589793

If you want to refer to the name of the class inside the body, you can define a named class expression. The name is only visible within the scope of the class expression itself:

const Animal = class NamedAnimal {
    constructor() {
    }

    whoIsThere() {
        return NamedAnimal.name;
    }
};

const obj = new Animal();

console.log(obj.whoIsThere()); // NamedAnimal

Instance methods

You can create class methods with the same syntax as object methods. A method is basically a function defined within the class scope and accessible to every instance of that class.

For example, in the Circle class above, we have already defined a method named area() that returns the area of the circle.

Let us define another class called Rectangle with a method named area() that computes and returns the area of a rectangle:

class Rectangle {
    constructor(width, height) {
        this.width = width;
        this.height = height;
    }

    area() {
        return this.width * this.height;
    }
}

const rect = new Rectangle(15, 20);

console.log(rect.area()); // 300

Static methods

A static method is a function defined within a class that can be accessed without creating a new object of that class.

Since static methods are defined on the class level, you can call them directly using the class name.

In JavaScript, you must use the static keyword to define a static method:

class Rectangle {
    constructor(width, height) {
        this.width = width;
        this.height = height;
    }

    static square(length) {
        return new Rectangle(length, length);
    }
}

const square = Rectangle.square(7);
square.height; // 7
square.width; // 7

Getters and setters

Just like an object-oriented class, a JavaScript class may also include getter and setter methods. You can use these methods to format and validate the class properties.

Here is an example of the User class that implements getters and setters:

class User {
    constructor(name, age) {
        // Invokes setter methods
        this.name = name;
        this.age = age;
    }

    get name() {
        return this._name;
    }

    set name(value) {
        this._name = value;
    }

    get age() {
        return `${this._name} is ${this._age} years old!`;
    }

    set age(value) {
        if (typeof value !== 'number') {
            throw new Error(`Age must be a number.`);
        }
        this._age = value;
    }
}

const john = new User('John White', 21);

console.log(john.name); // John White
console.log(john.age); // John White is 21 years old!

// Throws an error
const maria = new User('Maria', '32');
// Error: Age must be a number.

Notice the getter and setter methods for the age property. We are formatting the age value before returning it back. Also, when the age is set, we make sure that it is a number. When you try will set a non-numeric value for the age property, the setter method throws an exception.

Computed method names

You can also define computed method names by using the bracket [...] in a JavaScript class:

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

    ['hi' + 'There']() {
        return ` 👋 ${this.name}`;
    }
}

const alex = new User('Alex');

console.log(alex.hiThere()); //  👋 Alex

Inheritance

One of the benefits of using classes is that you can easily extend the functionality by creating a new class based on the parent class. This allows us to reuse the same code for other objects that are similar but need some additional or more specific features.

When a JavaScript class extends another class, it inherits all the static and instance methods, getters and setters, and computed properties.

The subclass then defines additional methods, statics, getters, and setters. It can also override the parent's class methods, statics, getters, and setters.

Here is an example of the Square class that extends the functionality of Rectangle:

class Rectangle {
    constructor(width, height) {
        this.width = width;
        this.height = height;
    }

    area() {
        return this.width * this.height;
    }
}

class Square extends Rectangle {
    constructor(length) {
        // `super` refers to the parent class' constructor
        super(length, length);
    }

    inradius() {
        return this.width / 2;
    }
}

const square = new Square(10);

square.area();          // 100 (from Rectangle)
square.inradius();      // 5 (from Square)

Take a look at this article to learn more about JavaScript classes, objects, and prototypes.

✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.