Classes in JavaScript: An Introduction

Hero image for Classes in JavaScript: An Introduction. Image by Ashkan Forouzani.
Hero image for 'Classes in JavaScript: An Introduction.' Image by Ashkan Forouzani.

Classes are a fundamental concept in objectoriented programming (OOP); they provide a way to organise code into logical entities that represent realworld objects or concepts, encapsulating data and functionality into reusable and modular components. JavaScript, as an OOP language, has supported classes since ES6, and they have become a crucial feature for modern web developers.

In this article, I aim to provide an introduction to classes in JavaScript, including basic and advanced examples, comparisons with other strategies, and potential issues that you as a frontend developer may encounter.


Basics of Classes in JavaScript

Classes in JavaScript provide a blueprint for creating objects with properties and methods. They are defined using the class keyword, followed by the class name, and an optional constructor method.

For example:

class Car {  constructor(make, model, year) {    this.make = make;    this.model = model;    this.year = year;    this.running = false;  }  start() {    this.running = true;    console.log(`Starting ${this.make} ${this.model} ${this.year}`);  }  stop() {    this.running = false;    console.log(`Stopping ${this.make} ${this.model} ${this.year}`);  }}

Here, we've defined a Car class with a constructor which accepts three parameters: make, model, and year. We've also defined two methods: start and stop, which set the running property and log a message to the console.

To use this, we create a new instance of the Car class using the new keyword like this:

const myCar = new Car('Volkswagen', 'Golf', 2016);

This creates a new instance of the Car class called myCar with the specified make, model, and year, which can be accessed like so:

console.log(myCar.make);  //=> 'Volkswagen'console.log(myCar.model);  //=> 'Golf'

More Advanced Class Use

So far we've only looked at fairly rudimentary use for class. Instead of a Volkswagen, let's embrace the electriccar future. In JavaScript, classes can also inherit from other classes using the extends keyword. For example:

class ElectricCar extends Car {  constructor(make, model, year, batteryCharge) {    super(make, model, year);    this.batteryCharge = batteryCharge;  }  start() {    super.start();    console.log(`The battery is charged to ${this.batteryCharge}%`);  }}

Here, we've defined a new class called ElectricCar, which extends the Car class, and we've added a new property called batteryCharge. Finally, we've overridden the start method to include a message about the battery charge (which you would presumedly receive whilst starting your car remotely).

To create a new instance of the ElectricCar class, we can use the same syntax as before, although with an additional argument:

const myElectricCar = new ElectricCar('Tesla', 'Model S', 2016, 95);

With this new electric car created, we can start it up remotely by calling the start method, which will also return the current charge level:

myElectricCar.start();  //=> 'The battery is charged to 95%'

Potential Issues

One potential issue with classes in JavaScript is that they are not true classes in the traditional computer programming sense. JavaScript uses a prototypebased inheritance model, which means that classes are essentially just syntactic sugar for creating objects and linking them together. As you might imagine, this can lead to some unexpected behaviour if you're not careful.

Another potential issue is that classes in JavaScript do not have private members or methods. Whilst you can use closures to achieve some level of encapsulation, it's not as powerful or flexible as true private members in other languages.


Alternative Strategies

Obviously, classes are relatively new, and developers have still had alternative strategies and patterns to implement objectoriented programming (OOP) concepts. For completeness, here are some of the common strategies used. Rather than using the carbased examples I've used above, I'm switching to a more triedandtested example of using people, which I feel is a little easier when offering multiple examples for the same (ish) outcome. Hopefully, the juxtaposition isn't too jarring.

Function Constructors

Developers use the Function constructor as a way to define a new function that can then be called with the new keyword to create an object. The new keyword creates a new object and sets the constructor property of the object to the constructor function that was called. For example:

function Person(name, age) {  this.name = name;  this.age = age;  this.greet = function () {    console.log(      `Hello, my name is ${this.name} and I am ${this.age} years old.`    );  };}let adam = new Person('Adam', 25);adam.greet();  //=> "Hello, my name is Adam and I am 25 years old."

Prototypes

In JavaScript, every object has a prototype, which is an object that it inherits properties and methods from. Prototypes allow developers to share code between objects and avoid duplicating code. For example:

function Person(name, age) {  this.name = name;  this.age = age;}Person.prototype.greet = function () {  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);};let max = new Person('Max', 25);max.greet();  //=> "Hello, my name is Max and I am 25 years old."

Object Literals

An object literal is a way to define an object using curly braces. Object literals are a simple way to create objects with properties and methods:

let owen = {  name: 'Owen',  age: 25,  greet: function () {    console.log(      `Hello, my name is ${this.name} and I am ${this.age} years old.`    );  },};owen.greet();  //=> "Hello, my name is Owen and I am 25 years old."

Factory Functions

A factory function is a function that returns an object. Factory functions can be used to create multiple instances of an object with different values. Here's our Person example again:

function createPerson(name, age) {  return {    name: name,    age: age,    greet: function () {      console.log(        `Hello, my name is ${this.name} and I am ${this.age} years old.`      );    },  };}let carl = createPerson('Carl', 25);carl.greet();  //=> "Hello, my name is Carl and I am 25 years old."

These are all objectorientation strategies which were used before classes were introduced in JavaScript, and are still widely used today. The choice of which strategy to use depends on the specific needs of the project and personal preference, although some are certainly easier to read than others...


The Wrap‑Up

Classes in JavaScript are a powerful and flexible tool for creating reusable and modular components in your code. By understanding the basic syntax and more advanced concepts, you can take full advantage of this feature and write more efficient and maintainable code. However, it's important to be aware of the potential issues and limitations of classes in JavaScript, so that you can avoid unexpected behaviour and write more robust code.


Categories:

  1. Front‑End Development
  2. JavaScript