Skip to content

Instantly share code, notes, and snippets.

@mckamey
Created January 13, 2012 20:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mckamey/1608507 to your computer and use it in GitHub Desktop.
Save mckamey/1608507 to your computer and use it in GitHub Desktop.
JS Module Pattern C
/*global jQuery */
// ensure root namespace
var App = App || {};
App.foo = (function($){
'use strict';
// private members
var foo = 0,
bar = 'bar';
function inc() {
bar = 'baz';
foo++;
}
// delayed initialization
$(function() {
inc();
});
// public members to be exported
return {
bar: function() {
return bar+' '+foo;
},
inc: inc
};
})(jQuery);
// minified via closure-compiler.appspot.com
var App=App||{};App.foo=function(d){function a(){b="baz";c++}var c=0,b="bar";d(function(){a()});return{bar:function(){return b+" "+c},inc:a}}(jQuery);

JS Module Pattern C

Conventions

  • The first statement of the script ensures the application's root namespace has been allocated by redeclaring and assigning itself logically OR'ing with an empty object literal: || {}.
  • The core of the pattern is the anonymous wrapper function, which is immediately executed leaving no trace.
  • The parameter list of the wrapper function includes all externally accessed references (including jQuery, document, window, etc.).
  • The wrapper function always returns the sub-module being defined.

Advantages

  • Provides slightly more terse module creation internally in the wrapper function but can still be assigned to a larger nested structure.

  • The root namespace does not need to be passed in if it isn't used internally.

  • The first statement ensures that the root namespace has been allocated before it is used but does not trample an existing instance if another module has already allocated it.

  • The anonymous wrapper function provides an isolated space where private members (fields and functions) can exist but aren't able to be read, changed or called from the outside context.

  • The parameter list explicitly documents all external references that are accessed by this module.

  • The arguments passed in do not need to be global references but instead could be references to repeatedly used sub-objects, e.g. document.body

  • The parameter list allows obfuscation tools to automatically compact very small var names even for global objects (see the minified version).

  • Other modules within the same root level namespace are able to be defined and included in any order (as long as they do not have inter-dependencies) without trampling each other.

  • The wrapper function provides a closure around the argument values ensuring the references aren't later changed out by another less-defensive script.

  • If the module is a namespace nested deeper than the first level, the initial line may be repeated for other intermediate levels and the immediate parent passed in rather than the root. For example:

    var App = App || {};
    App.foo = App.foo || {};
    App.foo.bar = (function(){ ... return { ... }; })();

Disadvantages

  • slightly less encapsulated generation of the app namespace.
  • The return value must always be returned and contain the module object, otherwise the application namespace will be incomplete leading to mysterious errors.
  • Only one root module may be built in the same script (NOTE: this is not really much of an issue as probably avoids an anti-pattern).
  • If var is not used to declare private members, they will actually be created in the global namespace.
  • The conventions must be followed otherwise the benefits of the pattern are not fully realized.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment