# Introduction to classes in JavaScript

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published Dec 18, 2020, updated Sep 10, 2022. Topics: JavaScript.
Canonical URL: https://attacomsian.com/blog/javascript-classes

> An introduction to JavaScript classes and how to define a class, static and instance methods, getters and setters, and more.

JavaScript is a prototype-based programming language, and each [object](https://attacomsian.com/blog/objects-prototypes-classes-javascript#objects) 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:
 
```javascript
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:

```javascript
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](https://attacomsian.com/blog/javascript-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:

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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`:

```javascript
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](https://attacomsian.com/blog/objects-prototypes-classes-javascript) to learn more about JavaScript classes, objects, and prototypes.
