JavaScript module pattern with example
In order to approach to Modular design pattern, you need to understand these concept first:
Immediately-Invoked Function Expression (IIFE):
(function() {
// Your code goes here
}());
There are two ways you can use the functions. 1. Function declaration 2. Function expression.
Here are using function expression.
What is namespace?
Now if we add the namespace to the above piece of code then
var anoyn = (function() {
}());
What is closure in JS?
It means if we declare any function with any variable scope/inside another function (in JS we can declare a function inside another function!) then it will count that function scope always. This means that any variable in outer function will be read always. It will not read the global variable (if any) with the same name. This is also one of the objective of using modular design pattern avoiding naming conflict.
var scope = "I am global";
function whatismyscope() {
var scope = "I am just a local";
function func() {return scope;}
return func;
}
whatismyscope()()
Now we will apply these three concepts I mentioned above to define our first modular design pattern:
var modularpattern = (function() {
// your module code goes here
var sum = 0 ;
return {
add:function() {
sum = sum + 1;
return sum;
},
reset:function() {
return sum = 0;
}
}
}());
alert(modularpattern.add()); // alerts: 1
alert(modularpattern.add()); // alerts: 2
alert(modularpattern.reset()); // alerts: 0
jsfiddle for the code above.
The objective is to hide the variable accessibility from the outside world.
JavaScript design pattern: difference between module pattern and revealing module pattern?
There are at least three different ways to implement the Module Pattern, but the Revealing Module Pattern is the only Module Pattern descendant that has an official name.
The Basic Module Pattern
The Module Pattern must satisfy the following:
- Private members live in the closure.
- Public members are exposed in the return object.
But there's a lot of ambiguity in this definition. By resolving the ambiguity differently, you get variants of the Module Pattern.
The Revealing Module Pattern
The Revealing Module Pattern is the most famous and most popular of the Module Pattern variants. It has a number of advantages over the other alternatives, such as
- Rename public functions without changing function body.
- Change members from public to private or vice versa by modifying a single line, without changing the function body.
The RMP satisfies three additional conditions in addition to those in the original:
- All members, whether public or private, are defined in the closure.
- The return object is an object literal with no function definitions. All right hand side expressions are closure variables
- All references are via the closure variables, not the return object.
The following example shows how it's used
var welcomeModule = (function(){
var name = "John";
var hello = function(){ console.log("Hello, " + name + "!");}
var welcome = function() { console.log( hello() + " Welcome to StackOverflow!");}
return {
name: name,
sayHello: hello,
sayWelcome: welcome
}
})();
If you wanted to make name
and sayHello
private, you just need to comment out the appropriate lines in the return object.
var welcomeModule = (function(){
var name = "John";
var hello = function(){ console.log("Hello, " + name + "!");}
var welcome = function() { console.log( hello() + " Welcome to StackOverflow!");}
return {
//name: name,
//sayHello: hello,
sayWelcome: welcome
}
})();
The Module Pattern with Object Literal
This is probably the oldest variant of the Module Pattern. Unlike RMP, there's no sexy official name for this variant.
It satisfies the following conditions, in addition to the original:
- Private members are defined in the closure.
- Public members are defined in the return object literal.
- References to public members are via
this
, whenever possible.
In the following example, you can see how, in contrast to RMP, the function definitions are actually in the return object literal, and references to members are qualified by this
.
var welcomeModule = (function(){
return {
name: "John",
sayHello: function(){ console.log("Hello, " + this.name + "!");}
sayWelcome: function() { console.log( this.hello() + " Welcome to StackOverflow!");}
}
})();
Note that unlike RMP, in order to make name
and sayHello
private, the references pointing to name
and sayHello
in the various function body definitions also have to be changed.
var welcomeModule = (function(){
var name = "John";
var sayHello = function(){ console.log("Hello, " + name + "!");};
return {
//name: "John",
//sayHello: function(){ console.log("Hello, " + this.name + "!");}
sayWelcome: function() { console.log( hello() + " Welcome to StackOverflow!");}
}
})();
The Module Pattern with Return Object Stub
This variant also has no official name.
It satisfies the following conditions, in addition to the original:
- An empty return object stub is defined at the beginning.
- Private members are defined in the closure.
- Public members are defined as members of the stub
- References to public members are via the stub object
Using our old example, you can see that public members are directly added to the stub object.
var welcomeModule = (function(){
var stub = {};
stub.name = "John";
stub.sayHello = function(){ console.log("Hello, " + stub.name + "!");}
stub.sayWelcome = function() { console.log( stub.hello() + " Welcome to StackOverflow!");}
return stub;
})();
If you want to make name
and sayHello
private as before, the references to the now-private members have to be changed.
var welcomeModule = (function(){
var stub = {};
var name = "John";
var sayHello = function(){ console.log("Hello, " + name + "!");}
stub.sayWelcome = function() { console.log( hello() + " Welcome to StackOverflow!");}
return stub;
})();
Summary
The differences between the Revealing Module Pattern and the other variants of the Module Pattern is primarily in how public members are referenced. As a result, RMP is much easier to use and modify, which accounts for its popularity. However, these advantages come at a great cost (in my opinion), which Addy Osmani alludes to in his post on the Revealing Module Pattern,
A disadvantage of this pattern is that if a private function refers to a public function, that public function can't be overridden if a patch is necessary. This is because the private function will continue to refer to the private implementation and the pattern doesn't apply to public members, only to functions.
Public object members which refer to private variables are also subject to the no-patch rule notes above.
As a result of this, modules created with the Revealing Module pattern may be more fragile than those created with the original Module pattern, so care should be taken during usage.
and which I've talked about in some other posts.
Javascript 'normal' objects vs module pattern
If you're only going to be using one instance per page, I don't see the need to involve the new
keyword. So personally I would create a revealing module like you did in your last example, and expose an object with the "public" properties.
Though I don't see your point with the getModel()
function, since MyModel
is obviously accessable outside of the scope.
I would have rewritten it slightly:
var LoginModel = (function(model, window, undefined){
function init(){ } // or whatever
function doSomethingWithModel(){
console.log(model);
}
return { init: init };
})(MyModel, window);
If you're uncertain of which modules that will get a model
, you can use loose augumentation and change
})(MyModel, window);
to
})(MyModel || {}, window);
If you need several instances of a module, it would look something like this:
var LoginModel = (function(model, window, undefined){
function loginModel(name){ // constructor
this.name = name; // something instance specific
}
loginModel.prototype.getName = function(){
return this.name;
};
return loginModel;
})(MyModel, window);
var lm1 = new LoginModel('foo');
var lm2 = new LoginModel('bar');
console.log(lm1.getName(), lm2.getName()); // 'foo', 'bar'
how to use the javascript module pattern in a real example?
This is quite an opinionated subject, but I'd do it (without entirely knowing your full app and what it does), somewhat like so:
var myApp = (function() {
var someElement = $("#foo"); //some element I know I'll use lots
var addMessage = function(message) {
$.ajax({
url: '/test',
type: 'POST',
dataType: "json",
data: {'message' : message},
success: function(data) {
...
},
error: function() {
...
}
});
};
var inputClick = function(event) {
event.preventDefault();
//depending on if you'll reuse these selectors throughout the app I might have these as variables
$('.loading').html('<img class="remove_loading" src="/graphics/loading.gif" />');
var message = $(".wallmessage").val();
if (message == ""){
$("#messageempty").jmNotify();
$('.remove_loading').remove();
} else {
addMessage(message);
}
};
var bindFunctions = function() {
$("input#share").on("click", inputClick)
};
var init = function() {
bindFunctions();
};
return {
// EDIT: 27/12/16 - need to return init for 'usage' example to work
init: init,
addMessage: addMessage
//anything else you want available
//through myApp.function()
//or expose variables here too
};
})();
//usage
myApp.init();
Your original code for the pattern is wrong, the function has to have ()
at the very end, to make it a function that is immediately invoked, and then executes, exposing anything through the return statement
.
You may wish to differ slightly from what I've done, it's only a basic idea but I hope it might get you started.
Someone a while back asked a question relating to this pattern and I answered it explaining why we use (function() {})();
and how the return
statement works in that context, if you're slightly confused by it that might be worth reading too.
why module pattern?
I think this example could help you to clarify the usefulness of the Module Pattern.
Module Pattern
The module pattern is widely used because it provides structure and helps organize
your code as it grows. Unlike other languages, JavaScript doesn’t have special syntax
for packages, but the module pattern provides the tools to create self-contained decoupled
pieces of code, which can be treated as black boxes of functionality and added,
replaced, or removed according to the (ever-changing) requirements of the software
you’re writing.
The module pattern is a combination of several patterns, namely:
- Namespaces
- Immediate functions
- Private and privileged members
- Declaring dependencies
The first step is setting up a namespace. Let’s use the namespace() function from earlier
in this chapter and start an example utility module that provides useful array methods:
MYAPP.namespace('MYAPP.utilities.array');
The next step is defining the module. The pattern uses an immediate function that will
provide private scope if privacy is needed. The immediate function returns an object - the actual module with its public interface, which will be available to the consumers of
the module:
MYAPP.utilities.array = (function () {
return {
// todo...
};
}());
Next, let’s add some methods to the public interface:
MYAPP.utilities.array = (function () {
return {
inArray: function (needle, haystack) {
// ...
},
isArray: function (a) {
// ...
}
};
}());
Using the private scope provided by the immediate function, you can declare some
private properties and methods as needed. Right at the top of the immediate function
will also be the place to declare any dependencies your module might have. Following
the variable declarations, you can optionally place any one-off initialization code that
helps set up the module. The final result is an object returned by the immediate function
that contains the public API of your module:
MYAPP.namespace('MYAPP.utilities.array');
MYAPP.utilities.array = (function () {
// dependencies
var uobj = MYAPP.utilities.object,
ulang = MYAPP.utilities.lang,
// private properties
array_string = "[object Array]",
ops = Object.prototype.toString;
// private methods
// ...
// end var
// optionally one-time init procedures
// ...
// public API
return {
inArray: function (needle, haystack) {
for (var i = 0, max = haystack.length; i < max; i += 1) {
if (haystack[i] === needle) {
return true;
}
}
},
isArray: function (a) {
return ops.call(a) === array_string;
}
// ... more methods and properties
};
}());
The module pattern is a widely used and highly recommended way to organize your
code, especially as it grows.
“JavaScript Patterns, by Stoyan Stefanov
(O’Reilly). Copyright 2010 Yahoo!, Inc., 9780596806750
Javascript Module Pattern with anonymous functions
It seems like you need to understand how return
works in functions in order to understand why the provided examples behave the way they do.
Example 1: You create a new variable pub
and adding two methods to it: add
and sub
. At the end, you're returning the pub variable to CalcModule
So when you call CalcModule
, it returns the following object with two methods:
CalcModule = {
add: function() {...},
sub: function() {...}
}
Example 2: Let's rewrite example 2 similar to example 1...
var testModule = (function () {
var counter = 0;
var pub;
pub.incrementCounter: function () {
return counter++;
}
pub.resetCounter: function () {
console.log( "counter value prior to reset: " + counter );
counter = 0;
}
return pub;
})();
We know pub
is an object...
pub = {
incrementCounter: function() { ... },
resetCounter: function() { ... }
}
and we're returning pub
to testModule
... therefore...
testModule = {
incrementCounter: function() {...},
resetCounter: function() {...}
}
Hope this is helpful.
JavaScript Module Pattern - Private variables vs. Static variables
You're right; _name
is more of a static variable. It is kept in the closure that contains the constructor, so every use of the constructor will use that same variable. And remember, this has nothing to do with classes, and everything to do with closures and functions. It can be pretty handy, but it isn't how you do private members.
Unsurprisingly, Douglas Crockford has a page devoted to private members in Javascript.
In order to make private members, you have to go 'one level deeper'. Don't use a closure outside of the constructor; use the constructor as the closure. Any variables or methods defined inside the constructor are obviously not usable by the outside world. In fact, they aren't accessible by the object, either, so they are rather extremely 'private'.
We want to use our private members though. :) So what to do?
Well, in the constructor, do this:
var Klass = function () {
var private = 3;
this.privileged = function () { return private; };
};
and then:
var k = Klass();
console.log(k.privileged()); // 3
See how that's using the constructor as a closure? this.privileged
lives on, attached to the object, and thus private
lives on, inside this.privileged
's closure.
Unfortunately, there's one problem with private and privileged methods in Javascript. They must be instantiated from scratch each time. There is no code sharing. That's obviously what we want with private members, but it isn't ideal for methods. Using them slows down object instantiation and uses more memory. It's something to keep in mind when/if you run into efficiency problems.
(Revealing) Module Pattern, public variables and return-statement
Does this actually mean, that I can't have any methods, that handle public properties?
No, it means that you cannot have public variables. var _public
is a variable, and it is not accessible from outside, and when you modify the private variable this will not be reflected in your public ._public
property.
If you want to make things public, use properties:
var a = function() {
var _private = null;
function init() {
_private = 'private';
this._public = 'public';
}
function getPrivate() {
return _private;
}
return {
_public : null,
init : init,
getPrivate : getPrivate,
}
}();
I can manipulate that public property, like a._public = 'public';. But I can't change it from within my object.
You can use this
in the methods of your object, as shown above. Or you use a
to reference the object, or possibly even store a local reference to the object you return. See here for the differences.
Or at least those changes aren't passed through
Yes, because variables are different from properties (unlike in some other languages like Java, and with exceptions for global ones). When you export public: _public
in your object literal, it takes only the current value from the _public
variable and creates a property on the object with it. There is no persistent reference to the variable, and changes to one are not reflected in the other.
Why isn't it possible to just use
return this;
to make everything public? As this should be the context of the self-invoked function, shouldn't it just return eveyrthing in it?
Variables are part of a scope in JavaScript. (Except for the global one) those scopes are not objects accessible to the language.
The this
keyword does not refer to this scope of the function, but to the context that was provided by the call. That can be the base reference in a method call, the new instance in a constructor invocation, or just nothing in a basic function call like yours (or the global window
object in loose mode).
Module Pattern still necessary now that javascript has native 'classes
The module pattern isn't only (or even primarily) used to mimic classes. It's proper modules, not classes, that make the old module pattern likely to become...if not obsolete, then a lot less-used, in the next few years. Those and private methods (which are currently a Stage 3 proposal) and perhaps to an extent private fields (also Stage 3).
But prior to proper modules, or sometimes even concurrent with them, you'd still use it if you want to have private functions or data or similar related to something which isn't private. Example:
const Foo = (function() {
function privateFunction(x) {
return /*...do something with `x`...*/;
}
class Foo {
dosomething(x) {
return privateFunction(x) ? "a" : "b";
}
}
return Foo;
})();
I'll also note that sometimes, you might use an anonymous block rather than an IIFE, since class
, const
, and let
have block scope. I wouldn't above because I'd have to make the outer Foo
non-constant (so I could assign to it in the block), but there are other times when it might apply...
Related Topics
Xmlhttprequest Status 0 (Responsetext Is Empty)
Space Filling with Circles of Unequal Size
Draggable Line Chart in R/Shiny
Javascriptcore Call Function with Callback Swift
Push Is Overwriting Previous Data in Array
Angular: Can't Find Promise, Map, Set and Iterator
Jquery Clone() Not Cloning Event Bindings, Even with On()
Maintain Model of Scope When Changing Between Views in Angularjs
Using Enter Key with Action Button in R Shiny
JavaScript Loops: For...In VS For
Shiny App:Disable Downloadbutton
Concerns, Decorators, Presenters, Service Objects, Helpers - Help Me Understand Them
How to Implement Ruby's Extend Module in JavaScript
Firebase.Database Is Not a Function
Finding Variable Type in JavaScript