javascript classes featured image

Working with JavaScript: How Classes Operate 

Introduction

Every object in JavaScript, a prototype-based language, contains an internal property named the [[Prototype]]. Its utility extends to the manipulation of object properties and methods. Mimicking the object-oriented design pattern of JavaScript, most developers utilize construction functions. One of these functions is the concept of classes, introduced to JavaScript via the ECMAScript 2015 language specification.

JavaScript’s classes provide a sharper, more elegant syntax, sometimes described as “syntactical sugar,” while not offering much along the way of supplemental functionality. The classes make the syntax more relatable for developers as other object-oriented languages generally also operate on this programming principle.

Functional Classes

A class in JavaScript is a function type that is declared with a class keyword. The following example will illustrate the function used for the function’s initialization, as well as the syntax expression you can use for declaring a class:

For now, the function we created was empty. Next, let’s use the Object.getPrototypeOf() method to access its [[Prototype]] function:

Output:

You can use a similar method in the recently created class:

Output:

Both code declarations (for class and function) will return a function [[Prototype]]. By using the new keyword, any function can become a constructor instance with prototypes:

Output:

Similarly, you can apply this to classes:

Output:

While both constructor examples we illustrate are empty, the underlying syntax is evidently serving to return the same result.

Class Definition

As you might recall, we created a text-based role-playing game in our prototype and inheritance tutorial. Let’s pick up that example and update the syntax to classes from functions.

Constructor functions are set with certain parameters.  Each of them is assigned this property, about the function. By convention, the first letter of the identifier will be capitalized:

We can observe a similar structure when this is translated to a class syntax:

Our familiarity with the syntax lets us know that the constructor function serves as the object blueprint. We can tell that by the capitalization of the first letter. The objective of our function is more clearly communicated by the class keyword. The main two differences are that instead of a function, we are initializing the class keyword, as well as the assignments being made to the constructor() method.

Methods of Definition

Commonly, constructor function methods are linked directly to the prototype, instead of being initialized. We can see this in the greet() method:

The method can be associated directly with the class, simplifying the syntax by utilizing classes. Still more concise, defining a method can be done shorthand, as defined in the ES6:

Let’s give these properties a visual test run by creating a new instance of Hero with the new keyword, then assign it some values:

To view more detail about our newly created object we can print it out with console.log(hero1):

javascript classes

The output of that action shows us a full audit of what manipulations have been applied to the  hero1 object such as the application for the constructor() and greet() functions to the _proto_ of the object (but not as a direct method of it). This becomes clear when generating constructor functions. Things are a bit more obscure when it comes to generating classes. While classes offer a simpler and more succinct syntax, it comes at the cost of some degree of clarity.

Class Extensions

One major advantage of constructor function and class applications is their ability to be extended into new object blueprints based on the attributable nature of their parent. By doing so, we avoid code redundancy. However, we still generate objects similar enough to others, yet more specific and refined in their features.

The creation of new construction methods can be accomplished by utilizing the call() method as can be visualized in the following example. Here, we will be creating Mage, a more specific character class. Then, we will assign Hero properties to it with call(), in addition to supplementing a property:

From this point forward new instances of Mage can be created using Hero’s properties and its own specific one that can be added:

Sending hero2 shows that based on the constructor, we have created a new Mage:

javascript classes 2

To access parent functions with ES6 classes, we use the super keyword instead of call, and when referring to the parent class, we will use extends:

We can now create a new instance of Mage the same way, then we can print hero2 to the workstation and be able to observe the output:

javascript classes 3

The output will be almost identical in this case, except for [[Prototype]] in the class construction will link back to the parent, Hero. Let’s compare the entire process of initialization, supplementing methods, as well as the inheritance of the constructor function and class in the following two code snippets:

While the syntax is significantly different, the final result is virtually identical. With classes, we get a more concise way of creating blueprints for objects. Constructor functions will let us have a refined picture of what’s happening under the hood.

Final Thoughts

This tutorial focuses on the key differences and similarities between JavaScript constructor functions and ES6 classes. Both will serve to exhibit the behavior of inheriting the properties of the parent object, behavior inherent to JavaScript.

In order to be an effective JavaScript developer, one must understand these prototypical inheritance attributes. Most JavaScript libraries, such as React often reference the class syntax, so it helps to be familiar with classes when working with the platform.

Here are some more resources from our blog that will help you further utilize JavaScript:

Happy Computing!