JS Inheritance - Part 2: Factory Functions vs. Classes
Tags: javascript, inheritance, prototypes, functional
Published: 2024-06-09 04:47:25

---
title: JS Inheritance - Part 2: Factory Functions vs. Classes
published: true
description: Exploring the differences between factory functions and classes in JavaScript, and why you might prefer one over the other.
tags: [JavaScript, Inheritance, Prototypes, FunctionalProgramming]
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8r3hr597c2eozk8sgcth.jpg
---

## JS Inheritance - Part 2: Factory Functions vs. Classes

## Introduction

Last time, we took a look at classes and prototypes in JavaScript. We compared constructor functions to classes and discussed how the `class` keyword introduced in ES6 aimed to simplify object-oriented programming in JavaScript. However, the introduction of classes did not solve all the problems associated with constructor functions. Today, we will explore different ways to declare an object in JavaScript and see if there is a need to use classes at all.

## Different Ways to Declare an Object

### Class

```javascript
class ClassCar {
    drive() {
        console.log('Vroom!');
    }
}

console.log(typeof ClassCar); // function

const car1 = new ClassCar();
console.log(car1.drive());
```

### Constructor Function

```javascript
function ConstructorCar() {}

ConstructorCar.prototype.drive = function () {
    console.log('Vroom!');
};

console.log(typeof ConstructorCar); // function

const car2 = new ConstructorCar();
console.log(car2.drive());
```

### Factory Function

```javascript
const proto = {
    drive() {
        console.log('Vroom!');
    },
};

const factoryCar = () => Object.create(proto);

console.log(typeof proto); // object
console.log(typeof factoryCar); // function

const car3 = factoryCar();
console.log(car3.drive());
```

Each of these strategies stores methods on a shared prototype and optionally supports private data via constructor function closures. In other words, they have mostly the same features and could mostly be used interchangeably. The question now is: you can, but should you?

## Factory Functions

We talked about constructor functions. We know that the `new` keyword is something that changes a regular function into a constructor function. If we want to free ourselves from the confines of the classical model, we have to embrace the prototypal model. In a prototypal model, objects inherit from objects. (Do you remember `Object.prototype`?) However, JavaScript lacks an operator that is responsible for such an operation. Instead, it has a `new` keyword that can produce a new object that inherits from `Object.prototype`. This was done on purpose to make it look familiar to classically trained programmers, but it failed miserably. It simply did not appeal to the classical crowd. Also, it obscured JavaScript from its real inheritance model.

## Should You Use Factory Functions Instead of Classes?

Much like `Array`, `class` is not a language feature; it’s syntactic obscurantism. It tries to hide the prototypical inheritance model and the clumsy idioms that come with it, and it implies that JavaScript is doing something that it is not. So, by design, there are no classes. However, JavaScript has all the necessary features to implement OOP; there was no need to add classes in ES6. It was added just so Java or C# developers can feel comfortable.

To put a fine point on that, a child of a prototype isn’t a copy of its prototype, nor is it an object with the same shape as its prototype. The child has a living reference to the prototype, and any prototype property that doesn’t exist on the child is a one-way reference to a property of the same name on the prototype.

Most of the time, classes in JavaScript don’t serve a good purpose; they are not really useful.

## Why We Should Not Use Classes

Much like `Array`, `class` is not a language feature; it’s syntactic obscurantism. It tries to hide the prototypical inheritance model and the clumsy idioms that come with it, and it implies that JavaScript is doing something that it is not. So, by design, there are no classes. However, JavaScript has all the necessary features to implement OOP; there was no need to add classes in ES6. It was added just so Java or C# developers can feel comfortable.

To put a fine point on that, a child of a prototype isn’t a copy of its prototype, nor is it an object with the same shape as its prototype. The child has a living reference to the prototype, and any prototype property that doesn’t exist on the child is a one-way reference to a property of the same name on the prototype.

Most of the time, classes in JavaScript don’t serve a good purpose; they are not really useful.

## Functional Programming for Life

In JavaScript, functions are first-class citizens. Functional programming is all about using functions to their fullest extent. Functional programming has come and gone and come back again. A couple of reasons why, in my humble opinion, we should try to understand the benefits of functional programming. One should just ask himself if factories are much more flexible than either constructor functions or classes, and they don’t lead people down the wrong path by tempting them with the `extends` keyword and deep inheritance hierarchies. There are many safer code reuse mechanisms you should favor over class inheritance, including functions and modules.

## Some Code to Prove It

So we could start with something like this:

```javascript
// class
class ClassCar {
    drive() {
        console.log('Vroom!');
    }
}

console.log(typeof ClassCar); // function

const car1 = new ClassCar();
console.log(car1.drive());
```

And a little refactor using modules:

```javascript
// Car.js

export function drive() {
    console.log('Vroom!');
}
export function stop() {
    console.log('Stopping');
}

// app.js

import * as car from './Car';

car.drive();
car.stop();
```

So we got rid of two keywords here: `new` and `class`. As we see in the above example, we do not really need them to achieve what we want to achieve. Another example would be:

```javascript
class Child extends Parent {}

// instead we could do

const fun = parent(child());
```

Here we also saw another keyword `extends` that has come and gone. Do we really need it? Answer: not really.

A real-life example utilizing such a programming style would be the [Fastify](https://www.fastify.io/docs/latest/Reference/Plugins/) framework for Node.js backend development.

Moreover, on the frontend, React has also ditched the old concept of `React.Component` and has moved towards [functional components and hooks](https://reactjs.org/docs/hooks-intro.html).

## Summary

Classes in JavaScript make things look more familiar to classically trained developers. However, it is only a sugar coating, and when uncovered, it reveals JavaScript's true nature. And the true nature of JavaScript is prototypical inheritance. So, if you are not one of the developers coming from OOP programming languages like Java or C#, then I strongly suggest stopping using classes and favoring objects and functions, and moving on to modules. This will be extremely beneficial if you want to work in frameworks like React or Fastify. JavaScript, like any other language, has good and bad parts. Surely, one of the best parts is the lack of classes and class inheritance. It might take some effort and time to truly master prototypal inheritance, but it is surely worth it.