JavaScript Modules

When programming with more advanced implementations of JavaScript, such as projects using Backbone.js, Node.js, RequireJS, or often some sort of combination of these, you will inevitably come across discussion about the concept of JavaScript modules. Modules are small pieces of decoupled code — code containing no or very few dependencies — that exist as standalone components. These modules can be used by an application to solve a particular problem. The use of modules is not a requirement to create JavaScript applications. They’re just a way of organizing code to solve common problems that arise when creating applications. In that sense, modules can be thought of as a “design pattern.” There may be cases where you want to use the module pattern in combination with other design patterns. Or, there may be where you’d want to use a different design pattern altogether. It all depends on the nature of the app you are building.

That being said, the use of modules can be a very flexible and commonly used pattern for many different types applications — from games, to web apps, to script loaders, to just about everything else. So it is definitely something worth knowing if you’re in the business of creating large-scale JavaScript applications.

So let’s take a look at a module in native JavaScript…

var moduleNamespace = (function () {

    var privateVariable;
    var privateMethod;
    privateVariable = 0;

    privateMethod = function( foo ) {
        console.log( foo );

    };

    return {
        
        publicVariable: "foo", 
        
        publicFunction: function( bar ) {
            privateVariable++;
            privateMethod(bar);
        }
    };
    
})();

In the code above we have a variable named “moduleNamespace” that is assigned to an anonymous Immediately-invoked Function Expression (IIFE) — also sometimes refereed to as a self-executing function. It’s basically a function that will automatically run in your application when it’s declared. The end result is that there’s no need to write moduleNameSpace(); elsewhere in our program.

There are a lot of benefits to doing things this way. For one, this gives us a way to mimic public and private properties and methods that you find in class-based languages like C++ and Java. The private variables and functions above would not be accessible outside the scope of the anonymous self-executing function. Another benefit is that we have a lot of functionality (and we can add much more) but the only component in the global namespace is the name of the module (in this case “moduleNamespace”).

We can access the private variables and methods of the module above through calling the public methods…

alert(moduleNamespance.publicVariable);
moduleNamespance.publicMethod("Testing");

There are other variations on this module pattern that a lot of developers use. Often times, developers will move all of the functions and methods out of the return object…

var moduleNamespace = (function () {

    // Private
    var privateVariable;
    var privateMethod;
    privateVariable = 0;

    privateMethod = function( foo ) {
        console.log( foo );

    };

    // Public 
    var publicVariable =  "foo";
        
    publicFunction = function( bar ) {
        privateVariable++;
        privateMethod(bar);
    };

    return {
        publicVariable: publicVariable,
        publicFunction: publicFunction
    };
    
})();

And then the return object will return a list of key properties matched to value methods and variables. A lot of times this effectively achieves the same thing. However, if we wanted to have a different “name” of a function mapped to the one inside our module we could do it by changing the return object to something like the following…

 
return {
    a: publicVariable,
    b: publicFunction
};

Then we’d call the module variables and methods like this…

alert(moduleNamespance.a);
moduleNamespance.b("Testing");

Sometimes that gives you a bit more flexibility in how you want your application to call your module methods and access your module’s variables.

Just a quick note about namespacing for modules. “moduleNamespace” is the only variable that’s exposed to the namespace above it (which in this case would be “window”). A lot of times applications will be contained inside of an “app” namespace (or whatever variable name is chosen) because it’s not really considered good-form to dump a bunch of global variables into the window object. When this approach is used at the top of every JavaScript file in the application you may see something like…

 
var app = app || {};

Note that the name of “app” is often different (sometimes it’s the name of the application). Basically this is saying that if app is already present in the window object make the variable “app” that you’re going to be using in the JavaScript file that contains your module or modules equal to the global app variable in window or make a new empty object called app if there is not a variable called app in window. This way, you can load your JavaScript files in any order that you want, synchronously or asynchronously, and you never have to worry about dependencies of the app object being present in the global window object in your individual JavaScript files.

Then you would have to add your module to the “app” namespace instead of the global namespace…

var app = app || {};

app.moduleNamespace = (function() {

    ...

})();

That in a nutshell is how to work with modules in JavaScript.

, , , , , 9bit Studios E-Books

Like this post? How about a share?

Stay Updated with the 9bit Studios Newsletter

0 Responses to JavaScript Modules

    Leave a Reply

    Your email address will not be published. Required fields are marked *