Constructor in JS

Constructor in JS

What is Constructor in Javascript? How to use it and what is the difference between Function Constructor and Class Constructor?

What is Constructor?

A constructor is a special type of function that is used to initialize an object when it is created. There are two types of constructors in Javascript based on syntax. The first one defined as a function and the second one defined via a constructor method in the class. In both cases, we use the new keyword to create a new instance of the object.

Object Constructor Function

Default constructor in JavaScript. It existed before the introduction of the ES6 specification, i.e. before the introduction of classes, and of course it still exists and is used.

We use the following convention when creating a constructor:

  1. When creating the name of a constructor function, we should start with a capital first letter.

  2. We should use the new operator to call the created constructor.

Example:

function Player() {
    this.nickname = 'Rambo',
    this.level = 1
}

We have created a constructor function called Player, for now without any parameters inside the parentheses. Additionally, inside the constructor, we assigned the nickname and level properties to the word this. And we have assigned default values for these properties (Rambo, 1). The this keyword is an object that specifies a context (in this case the Player() context), and is used to refer to that context and assign values to its properties.

Constructor usage example:

const newPlayer = new Player();
console.log(newPlayer); // Output: {nickname: 'Rambo', level: 1}

In the above example, a new instance of the Player object was created using the new operator, and we also assigned it to the newPlayer constant. The value of newPlayer is the same as Player because we did not pass any new values to the function constructor.

Now let's try to pass the data when calling a new instance of the function constructor. For this purpose, we must specify the parameters when creating the constructor.

// Creating constructor function with two parameters
function Player(nicknameParam, levelParam) {
    this.nickname = nicknameParam,
    this.level = levelParam
}
const newPlayer = new Player('Terminator', 70);
console.log(newPlayer); // Output: {nickname: 'Terminator', level: 70}

In this example, we invoked a new instance of the constructor with two new arguments (Terminator, 70) that were assigned to the nickname and level properties from the context of the Player object. These values were returned when newPlayer was called.
Why are these values returned even though we don't see the return declaration there? Because the return declaration is added at the end by JavaScript, when the new operator is used and a new instance of the object is invoked.

function Player(nicknameParam, levelParam) {
    // this = {}; <- creating empty object for context
    this.nickname = nicknameParam,
    this.level = levelParam
    // return this;
}

Therefore, it is important to use the new operator when creating a new object. Without it, JS will read the call as a function without a return declaration and return undefined.

function Player(nicknameParam, levelParam) {
    this.nickname = nicknameParam,
    this.level = levelParam
    // no return statement
}
const newPlayer = Player('Terminator', 70);
console.log(newPlayer); // Output: undefined

Class constructor

In the ES6 specification (ECMAScript 2015), classes were introduced into the JacaScript syntax, and it is possible now to use a constructor within them.
Like function constructor, class constructor is a special method for configuring new objects, but now integrated into the class structure. This makes the syntax clearer and the constructor can e.g. access and use class features such as inheritance using the super keyword.

Below is the same example we already know, but using class:

class Player {
    constructor(nicknameParam, levelParam) {
        this.nickname = nicknameParam;
        this.level = levelParam;
    }
}
const newPlayer = new Player('Terminator', 70);
console.log(newPlayer); // Output: {nickname: 'Terminator', level: 70}

Above we used the classPlayer and in it we defined a constructor with parameters and properties. Notice that now the constructor is created using the constructor keyword. To create a new instance of class, or more specifically the constructor of the Player class, we still use the new operator, and in this case we even have to, because JS requires it. If we do not do this, we will receive an error.

It is possible to omit the constructor when creating a class if we do not use any additional object initialization.

class Player {
   nickname = 'Rambo';
   level = 1;
}
const newPlayer = new Player();
console.log(newPlayer); // Output: {nickname: 'Rambo', level: 1}

Inheritance

As mentioned earlier, in ES6 classes introduce the possibility of inheritance, i.e. the ability to take over the entire functionality of the parent class and the possibility of adding additional classes.

For better understanding, I will explain it with an example:

class PlayerInfo {
    constructor(nicknameParam, levelParam) {
        this.nickname = nicknameParam;
        this.level = levelParam;
    }

    getPlayerInfo() {
        return `Your character ${this.nickname} has level ${this.level}.`
    }
}
const newPlayerInfo = new PlayerInfo('Terminator', 70);
console.log(newPlayerInfo.getPlayerInfo()); 
// Output: Your character Terminator has level 70.

We have created a base class that takes two parameters nicknameParam, levelParam and has a getPlayerInfo function that returns text.

Now let's try to create another one that will inherit from the PlayerInfo class:

class PlayerFullInfo extends PlayerInfo {
    constructor(nicknameParam, levelParam, activeSubscribtionParam) {
        super(nicknameParam, levelParam);    
        this.activeSubscribtion = activeSubscribtionParam;
    }
    getPlayerInfo() {
        const subsctibtion = this.activeSubscribtion ? 'active' : 'inactive';
        return `Your character ${this.nickname} has level ${this.level} 
        and your subscribtion is ${subsctibtion}.`;
    }
}
const newPlayerFullInfo = new PlayerFullInfo('Rambo', 20, true);
console.log(newPlayerFullInfo);
// Output: {nickname: 'Rambo', level: 20, activeSubscribtion: true}
console.log(newPlayerFullInfo.getPlayerInfo());
// Output: Your character Rambo has level 20 and your subscribtion is 
// active.

When creating a new PlayerFullInfo class, we used the extends keyword to indicate which class we will inherit from.
Then we used the super keyword in the constructor properties to call the code from the constructor of the class we are extending. Additionally, we created the getPlayerInfo() method which, although it has the same name as in the PlayerInfo class, is overwritten and returned when newPlayerFullInfo.getPlayerInfo() is called.

Why do we need a constructor?

By using a constructor function, you can easily create multiple objects with the same properties and behavior without having to manually set them for each object. We also gain benefits such as: encapsulation, inheritance, so our code becomes more reusable, consistent and easier to maintain.