Javascript Module Pattern: A Detailed Deconstruction
The term module is a convention used in Javascript to group code that’s conceptually coherent. The Module Pattern is a programming design pattern that uses modules as the basic construct for organizing code.
Wikipedia defines Modular Programming as follows
[…] a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality.
The basic module
The absolute most basic Javascript module is actually a Javascript object
var Module = {
foo: 'hello world'
}
By itself this doesn’t seem like a very useful pattern but just by grouping under this object all variables needed we can get a great replacement for global variables
var Module = {
foo: 'hello world',
bar: 12345,
baz: ["John", "Joe", "Josh"],
qux: {x: 100, y: 300}
}
The Object-Module Pattern
Javascript object keys can hold functions also, which means that this simple module is a quick way to package our code consisting of both variables and functions.
var Module = {
foo: 1
bar: function() {
console.log(foo); // ReferenceError: foo is not defined
console.log(this.foo); // 1
console.log(Module.foo); //1
}
};
Public access
Variables defined as in the example above are public and can be access directly
Module.foo = 3;
Module.bar();
Within the module’s bar
the value of this
equals Module
, which means that the following two lines are equivalent when used inside bar
console.log(this.foo);
console.log(Module.foo);
Trying to access foo
without the this
qualifier or the namespace Module
will throw a Reference error since there is no foo
global variable defined.
Dynamic content
Modules allow for new variables to be added on the fly. This code is ok even if we’ve never declared the qux
member before.
Module.qux = 2;
This simple module pattern is more a Javascript code grouping technique. It is the most basic example of Javascript namespacing and a good replacement for using any global variable. You should always be able to replace all your global variables and functions for this code:
var MyNamespace = {};
MyNamespace.qux = "my new namespaced var (aka global)"
Full Example
Here’s a complete example of this Module Type:
var Module = {
foo: 1
bar: function() {
console.log(this); // ok! (=Module)
console.log(++this.foo); // ok!
console.log(++Module.foo); // ok!
}
};
// Public access
console.log(++Module.foo); // ok!
Module.bar();
// Allows for new variables to be added on the fly
Module.qux = 2;
The Functional-Module Pattern
The Functional-Module Pattern is very similar to the Object-Module described above, but instead of creating an object directly through the object notation, we create it as a result of executing a function.
Compare
var Module1 = {
foo: 10,
bar: function(){ alert("hi");}
}
with
var Module2 = (function(){
return {
foo: 10,
bar: function(){ alert("hi");}
};
}());
both Module1
and Module2
define an identical object, but utilizing the second syntax we can take advantage of closures.
The Closure-Module Pattern
A Closure is a function, plus the environment (or scope) it was declared in. Only functions, created inside functions are closures, and they can make our objects a tad more powerful and a lot more secure by:
- Data encapsulation: providing private member fields and methods
- Persistence of local scope: allowing public and private methods access to a private scope unique to the Module at hand
Implementing Private Members
In the example below the variable _foo
can be considered as a private member:
var Module = (function(){
var _foo = 20;
return {
bar: function(){ alert("hi");}
};
}());
_foo
is inaccessible to external code and so this code will return ‘undefined’
console.log(Module._foo); // undefined
(By the way, naming private variables starting with _
is a good common practice to easily differentiate between public and private variables and functions).
Taking advantage of the local scope
bar
in the example above, however, is truly private and could be used with in the public (and private) functions declared inside Module
. See the example below:
var Module = (function(){
var _foo = 20;
return {
bar: function(){ console.log(_foo);}
};
}());
Calling the public method bar
of Module
will output the value of _foo
, however trying to access the value directly from outside of Module
will now work
Module.bar(); // 20
console.log(Module._foo); // undefined
We have effectively created a private variable that’s inaccessible to code outside of Module
that can be used by internal functions for keeping the local state.
Closures are great when writing APIs and code to be used by other developers while keeping the integrity of the API itself.
Dynamic Members
The Module Pattern permits us to have, not only public and private members, but also dynamic variables and functions. Since the returned Module
is a regular Javascript object we can extend it as we would normally do in Javascript
Module.qux = 20;
Module.qux = function(){ console.log(this.qux); };
The —so called— Constructor
So up until now I’ve used this format of the Module pattern:
var Module = (function(){
var _foo = 0;
return {
bar: 1,
}
}());
I personally find that using a more explicit format makes it more clear to read and understand. Here:
var Module = (function(){
var _foo = 0;
var self = {
bar: 1,
}
return self;
}());
In this case it is clear that the value of Module is the object self
returned by the function. This is informally called the constructor of the Module.
Even better, this exact same thing can be expressed as:
var Module = (function(){
var _foo = 0;
var self = {};
self.bar = 1;
return self;
}());
I like this last representation best since it consists mostly of regular Javascript functional expressions (vs. object notation).
Self-referencing
Using this —so called— constructor syntax gives us a way to reference the module itself from within the module’s private member functions. Without a variable self
a private method would have no means to call a public variable or function.
Self-referencing varies depending on the scope of the caller and the callee. What this means is that in order to call a function of a module we must understand the scope of the function that’s calling and the function that’s being called, since there are rules for each.
Private access within a Module
Accessing private members can be done directly without any qualifier from private or public functions. Dynamic functions can’t access private members.
var Module = (function(){
var _foo = 10;
var _bar = function (){ console.log(_foo)};
var self = {
baz: function (){ console.log(_foo)};
}
return self;
}());
Public access within Module
Accessing public members from within private or public functions can be done using the self
variable. Additionally public functions can also access public members via ‘this’ keyword.
var Module = (function(){
var _foo = function (){ console.log(self.bar)};
var self = {
bar: 1,
baz: function (){ console.log(self.bar)}; // this works
qux: function (){ console.log(this.bar)}; // this works too
}
return self;
}());
Access from within dynamic members
Dynamic functions must always use the keyword this
to access public and other dynamic members. This is one of the awesome things about Javascript closures. Since the dynamic functions were not in the same scope as the Module
itself when created, they don’t have access to private methods (not even self
). That means that developers can’t use dynamic members to get around the private scope limitations.
var Module = (function(){
var _foo = 10;
var self = {
bar: 20,
}
return self;
}());
Module.qux = (function(){
console.log(this._foo); // undefined
console.log(this.bar); // 20
});
Summary
There are several ways to express the Module patter and all of them are equivalent. In any case taking advantage of closures will make modules that much more powerful.
Closure-based Pattern
This is the minimum expression of the Module Pattern. I personally like this syntax best, since I believe it offers best readability:
var m = (function(){
var _foo = "I'm private";
var self = {};
self.bar = "I'm public";
return self;
}());
A complete example: All put together
Here’s a complete example that shows public and private variables and functions.
var Module = (function(){
// private variables
var _v1 = 10;
// private methods
var _f1 = function(){
console.log(_v1);
console.log(self.v2);
console.log(self.v3);
};
// constructor
var self = {};
// public variables
self.v2 = 20;
// public functions
self.f2 = function(){
console.log(_v1);
console.log(self.v2);
console.log(self.v3);
};
return self;
}());
// Dynamic Members
Module.v3 = 30;
Module.f3 = function(){
console.log(this.v2);
console.log(this.v3);
};
// Usage
console.log(Module.v2);
Module.f2();
console.log(Module.v3);
Module.f3();
References
September 6, 2013 ☼ code