A Variation of JavaScript Module Pattern
May 25, 2012
Module Pattern is one of the most popular JavaScript design patterns today. It has a number of flavors in existence but all of
them are based on the same desire to encapsulate and protect the private state of an object. As you know, vanilla JavaScript does not have
private or
protected keyword that would make a property of an object private. All of the properties and methods of
any JavaScript object are inherently public and anyone can change, overwrite or even delete them. This is where the module pattern
comes in.
All variations of module patterns are based on JavaScript closures. JavaScript closure provides a convenient way to
create a private state and protect it. Module pattern has evolved over the course of almost 10 years and as a starting point I
am going to use revealing module pattern, which we in our development team just call the module pattern.
A self-invoking function is assigned to a variable thus creating a JavaScript closure with a private variable scope. The beauty of
this pattern is that you can expose only the properties and methods that you want keeping the rest of them protected in the closure.
But, there is a problem with this pattern. If you start developing very complex JavaScript applications, you will notice that
this pattern does not allow you to split the code into multiple files. All of the functions have to be within a single file. This
problem is easy to solve with the pattern below. I have also added a few methods and functions that help me demonstrate the beauty
of this approach.
This pattern allows the use of the module even before it is loaded. For example, in the course of your application, you need to
load a module as a separate script. However, before you load it, you want to pass a few variables to it.
In line 1, we declare the module variable as an empty object, if it was not declared before. Then, in lines 2-3 we set a few public
properties that will be passed to the module while it asynchronously loads. The content of the file module.js can be like this
You can augment this module at any time in the future. All you need to do is to repeat the basic structure of the module.
For example, if in addition to the code above you execute the following code
it will extend the module with
doSomething() method.
The Prettiest Form
My favorite and, arguably, the most prettiest form of the module pattern with augmentation is achieved when we
call it and pass the context.
Besides using
call to invoke the module, this version also uses functional declaration for internal methods, not functional
expressions. If you assign a function to a variable you cannot use this variable before it was declared. However, if you use functional
declarations, you can use them before they were declared. This allows to use functions and then exit the module with
return this,
while the implementation of the module follows below. In my view it makes the code easier to follow in large applications.
The Private Problem
There is one grave problem with the augmented module pattern that is hard to solve. The problem is that augmented portion of the
module has no access to the private variables of the original module. In fact, because those are two different JavaScript functions,
they have 2 different variable scopes and there is no way to share them.
Looking for a solution, I have come across an
article
by Ben Cherry that proposes to solve this problem by sealing and unsealing the private variables. While this is a solution to the
problem, I do not think it is the prettiest one. The problems with this approach are numerous:
- As a developer you have an additional burden to seal and unseal private scope.
- Private scope must be encapsulated into an object or you would have to seal and unseal each and every variable.
- Private scope is not completely protected because anyone can seal and unseal it if they know what they are doing.
There is another solution - JavaScript
eval() function. I am not a big fan of
eval(), but if it can solve the
problem it is worthwhile to give it a shot. Below is a simple example how
eval() can be used
At first I thought I can write a library where I can "hide"
eval() and it would do the job for me, but soon I have realized that
in order to access the private scope
eval() has to be executed where private scope is visible. Therefore, it must be used within the
module function or within any sub-function of the module function. On the bright side, you can also augment the module following the same
pattern and executing it with
eval().
Lastly, there is one more resources I would recommend for further reading. Addy Osmani has written a book called
Learning JavaScript Design Patterns where he describes lots
of different design patterns from JavaScript perspective. It certainly has been a helpful resource for me.
User Comments