Classes in JS

August, 2021822 words

Scrolling through Twitter, I've seen quite some people talking about how JS is not that different than languages like Java, Swift, C++ since it has features like classes, inheritance, ...

Although I like when people want to use language features, if they are there why not use them? But for me, it's still important that the basics behind those features are still understood correctly.

JS has no classes

Many reading this will probably say, that's wrong. JS has classes, because:

  • we can define how an object will look like
  • we can use inheritance to share behavior
  • we can instantiate an object from a class' constructor

And that's correct... At least partially. JS has a feature that lets developers create a blueprint for an object we can later create, but really this is only "syntactic sugar". This means that although you'll probably write a class like so

class Person {
...
}

this doesn't change the way JS will handle this class internally. To understand this better, we need to talk about what makes JS so special in the first place.

Classes vs Objects

When you think of Java, you probably think about how you create a class in one place and use this class through an instance in another place. This means you split the class from the instance. While the class defines the blueprint you want to use to build an object, the instance of that class is the thing that stores state, that you pass around and that provides all of the behavior defined in the blueprint.

Now here's the catch... JS doesn't actually work like that. JS doesn't have the distinction between a class and an instance of the class, in JS everything is an object. If you want to define a new object in JS you essentially use a base object as a starting point and add properties to it.

const obj = {};
obj.method = function() { ... }

If you were to do this in a large-scale application, I promise the code would be a mess. Not only would you have to create this object manually wherever you need it, but you'd also have no way to check if an object is of a specific type. For sure, although JS works differently in terms of class vs. instance, we still need a way to define a common blueprint that every object uses.

You could write a custom function that creates an object, adds properties to it, and returns it, but since this is such a common task to do, JS has such a feature built into its language.

Constructor functions

As the name suggests, constructor functions are special functions used to define what an object should look like. Later, if you want to use this object, you call this function and get a new object that looks identical to the one defined in the constructor.

function Person() { ... }

This function is in fact a constructor function. As you can see, nothing is different from a regular function. If you want to add properties to the object you create from that constructor, you can define those inside of the function.

this.name = ...
this.age = ...

Since these functions are just regular functions, you can also add parameters to them and use those within the body of the function. Now imagine you would just replace that first line in the function declaration with the constructor keyword from Java. There... It will look like a regular constructor from a class-based language.

The new keyword

Those familiar with JS might be wondering now, since you use this inside of the function, what is its value? As you know, the `this in a function declaration is determined by how a function is called. The problem with constructor functions is, we don't really have an object available just now, because the whole point of the function is to create that specific object for us. Luckily, JS has a neat solution for that too. If you want to call the constructor function, instead of calling it like

const person = Person()

you want to place the new keyword in front of the call.

const person = new Person()

This makes sure that a new object is created, this object will be available inside of the constructor as this, and when the constructor returns, you will get back this object with all its properties attached to it. Now you can call this function as many times as you want, and you will always get the exact same object shape back.

Conclusion

What's important to understand about JS is, it doesn't really know a concept of a class and an instance since everything we use is an object. Through constructor functions we get a mean to create blueprints for objects which makes it easier for us to use these throughout our application. One of the most important things still not covered is, how can we make use of inheritance in JS? This works through a concept known as a Prototype. What that is and how it works in JS is gonna be the next topic for the blog.