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.
Here we have a simple class Person
with a name
property and a method that uses that property.
|
|
Now if we just instantiate that class and call its method it will be just fine.
|
|
But what if I pass introduceYourSelf
to another function?
Let’s say we want to trigger the introduction when a button is clicked.
|
|
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.
|
|
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?
|
|
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.