
Classes in JavaScript: An Introduction

Classes are a fundamental concept in object‑oriented programming (OOP); they provide a way to organise code into logical entities that represent real‑world 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 front‑end 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 electric‑car 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 prototype‑based 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 object‑oriented programming (OOP) concepts. For completeness, here are some of the common strategies used. Rather than using the car‑based examples I've used above, I'm switching to a more tried‑and‑tested 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 object‑orientation 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:
Related Articles

Comparing Arrays in JavaScript. Accessing a Random Element from an Array Using JavaScript. Accessing a Random Element from an Array Using JavaScript
Setting CSS Blur Filter to Zero on a Retina Screen. Setting CSS Blur Filter to Zero on a Retina Screen

Introducing Seeded Randomisation into an SSR Gatsby Project. Introducing Seeded Randomisation into an SSR Gatsby Project

Exploring the Liquid Templating Language. Exploring the Liquid Templating Language

Understanding the Backtracking Approach: Solving the 'Word Search' Problem. Understanding the Backtracking Approach: Solving the 'Word Search' Problem

Hiding Empty Elements with CSS. Hiding Empty Elements with CSS

Testing Vue Components with Vue Test Utils. Testing Vue Components with Vue Test Utils

Harnessing the Power of Prototype.bind(). Harnessing the Power of
Prototype.bind()
Static Generation vs. Server‑Side Rendering in Next.js. Static Generation vs. Server‑Side Rendering in Next.js

Enhancing User Experience with CSS and JavaScript Animations. Enhancing User Experience with CSS and JavaScript Animations

JavaScript's hasOwnProperty() Method. JavaScript's
hasOwnProperty()Method