Contents

Factory Functions in JavaScript

A factory function is a function that creates objects and returns them.

Factory functions are useful because they allow to yield objects without using classes and the new keyword, which it’s better to avoid in JavaScript when possible.

Why avoiding classes

JavaScript has no idea what classes are because it is not an object-oriented language.

Yes, everything in JavaScript is an object but they are very different from the ones used in real OO languages such as Java or C#.

Let’s see some of the main reasons why it’s better to avoid classes.

Binding issues

You will encounter unexpected behaviors when you try to pass your class methods as callback to external methods/functions.

Let me show you with an example.

Example

Here we have a simple class Person with a name property and a method that uses that property.

1
2
3
4
5
6
7
8
9
class Person {
    constructor(name) {
        this.name = name
    }

    introduceYourSelf() {
        console.log(`Hi, I'm ${this.name}`)
    }
}

Now if we just instantiate that class and call its method it will be just fine.

1
2
const fabrizio = new Person('Fabrizio');
fabrizio.introduceYourSelf() // Hi, I'm Fabrizio

But what if I pass introduceYourSelf to another function?

Things will break

Let’s say we want to trigger the introduction when a button is clicked.

1
2
3
const button = document.getElementById('my-button')
button.addEventListener('click', fabrizio.introduceYourSelf)
button.click() // Hi, I'm

We would expect it to work but surprisingly it won’t.

The reason is because the this keyword will refer to the object it was passed to instead of the class the callback method comes from. In the example above this will refer to the button element.

There are some work around to this problem, like using the bind function, but generally speaking they create unnecessary convolution.

Private variables

They simply don’t exist in JavaScript.

Hierarchical dependencies

One of the pillars of OOP is inheritance but the problem with it is that it creates a hard to change top-to-bottom dependencies structure. That’s why you should prefer composition instead.

In other words using factory functions instead of classes might save you headaches once your application starts growing.

Let’s use a factory function

Let’s take the example above and re-write it as a factory function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const createPerson = n => {
    const name = n

    return {
        introduceYourSelf: () => console.log(`Hi, I'm ${name}`)
    }
}

const fabrizio = createPerson('fabrizio')
fabrizio.introduceYourSelf() // Hi, I'm Fabrizio

So far every thing works just like our class. But what if now we try to pass fabrizio.introduceYourSelf to an event listener as we did before?

Success
1
2
3
const button = document.getElementById('my-button')
button.addEventListener('click', fabrizio.introduceYourSelf)
button.click() // Hi, I'm fabrizio

It now works as expected because by not using this, the reference to the name variable will always be correct.

In addition, the name variable is now truly private because not directly accessible outside the createPerson function.

Conclusion

Factory functions are preferable over classes because they make code simpler to reason about.

However, they have slightly worse performances compared to classes therefore if your application needs to create a lot of objects, and by a lot I mean in the range of thousands per frame, then you might consider classes as a better option. Otherwise go safe with factory functions.