DEV Community

Kabir Nazir
Kabir Nazir

Posted on • Updated on

Prototype in Javascript - 04 - Using classes to create objects

In the previous article, we saw how we can use functions to create objects using the new keyword. We also saw one can assign the prototype to objects created using these functions by calling Function.prototype on the function itself. However, there was one slight inconvenience that we had noticed with this method. Let us see with an example.

    function User(name, score) {
      this.name = name;
      this.score = score;
    }

    User.prototype.incrementScore = function() {
      this.score++;
    };

    let user = new User('Kabir', 5);
    user.incrementScore();
Enter fullscreen mode Exit fullscreen mode

As you can see above, the code for creating a User object is stored in the User constructor function. The code for setting its prototype method is in another block of code below. This might make it harder for one to debug issues with prototype tracing. Hence, Javascript had introduced the 'class' construct, which solved a lot of issues with regards to object-oriented programming in the language.

The class construct

Let us see with a quick example of how we can use class to implement the same code as above.

    class User {

      constructor(name, score) {
        this.name = name;
        this.score = score;
      }

      incrementScore() {
        this.score++;
      }
    }

    let user = new User('Kabir', 5);
    user.incrementScore();
Enter fullscreen mode Exit fullscreen mode

In the above code, we have seen a class with the name 'User' being defined. When new User() is called, the following things happen:

  1. A new object is created
  2. The code in the constructor function of User class is run, with this inside that function pointing to the newly created object. The arguments passed to the new User() call are the arguments used in the constructor function (in this case, 'Kabir' as name and score as 5).
  3. This object is then returned.

We have also added a method called incrementScore in the class body as well. This method gets added to User class's prototype.

Before we proceed further, let us first understand how a class works in Javascript under the hood. Let us call typeof on User and see what gets returned in the console

    console.log(typeof User); // prints function
Enter fullscreen mode Exit fullscreen mode

The truth is that class in Javascript is somewhat of a 'syntactic sugar'. This means that, under the hood, it works in almost the same way that creating an object using a function would work. The code for class User written above actually does the following:

  1. Create a function called User. The function's body code is taken from the constructor method of the class.
  2. Any other methods present in the class are added to the prototype of User function.

Hence, in our above example, the User class had created an object with the name and score properties, as well as including the incrementScore function in its prototype.

Although class is considered a syntactic sugar, there are still a few important differences between using a class or simply a function to create objects. But we wouldn't be delving into that in this article as the focus here is on prototypes only.

Inheritance in classes

Now that we have seen how the prototype is set in a class, let us further proceed to how class inheritance works too. This is achieved using the extends keyword. Let's say we have a Bird class.

    class Bird {
      constructor(name) {
        this.name = name;
        this.canFly = true;
      }

      sing() {
        console.log(this.name + ' is singing');
      }
    }

    let myBird = new Bird('My bird');
    myBird.sing(); // My bird is singing
Enter fullscreen mode Exit fullscreen mode

Say we would like to create another class for an Eagle. But we wish to reuse the Bird class for common properties. Or in other words, have Eagle class inherit from the Bird class. This is achieved as follows:

    class Eagle extends Bird {
      attack() {
        console.log(this.name + ' is attacking');
      }
    }

    let eagle = new Eagle('Bald eagle');
    eagle.attack(); // Bald eagle is attacking
    eagle.sing(); // Bald eagle is singing
Enter fullscreen mode Exit fullscreen mode

The Eagle class is defined above, along with extends Bird. This means that the Eagle class has access to the properties and methods (including the constructor) defined in Bird class. This is because the extends keyword tells Javascript to set the prototype of Eagle.prototype to Bird.prototype. In other words, Eagle.prototype not only has a method called attack(), but also has it's __proto__ property set to Bird.prototype. This allows objects created using the Eagle class to have access to methods in the Bird class due to the prototype chain. One can also say that the Eagle class is the child class of its parent class, which is the Bird class.

There are some other concepts in class like the super method and method overriding that explain the behavior of child classes when created. I shall cover them and more in my next article on classes in Javascript.

This concludes my series on prototypes in Javascript. Hope you found it helpful.

Top comments (0)