More about modules: augmentation

In the previous posts, I’ve introduced some basics aspects related to the implementation of the module pattern in JavaScript. Even though it introduces several benefits, there are some problems that might make you think that this pattern isn’t for you. For instance, if you’re working in a team where several members are contributing to the same module at the same time, then your best option is to spread  the module across different files.

Before going on, I must confess that splitting modules across different files isn’t really something I love. Whenever I’m facing this decision, I always try to re-check my code and see if I can refactor it so that a module is defined in a single file. There are, however, some cases where that isn’t possible and in those cases we need strategies like augmentation. The best way to illustrate it is to show an example. We’ll augment the module introduced in the previous post by adding a new method. Here’s one way to do it (notice that this code should be placed into a different JavaScript file):

var obj = (function(baseModule, $) {
    var someOtherValue = "private 2";
    function printAnotherValue(elemSelector) {
        $(elemSelector).text(someOtherValue);
    }
    baseModule.printAnotherValue = printAnotherValue;
    return baseModule;
})(obj, jQuery);
obj.printValue("#info");
obj.printAnotherValue("#info2");

Notice that this second anonymous function receives a reference to the original module which is being augmented (besides the jQuery global reference). There’s a slight gotcha with the previous code: you need to preserve the correct order when importing the files of the module. In the previous sample, that is not needed because none of the files uses properties defined in the other module, so we should do everything in our power to remove that dependency. Fortunately for us, we can remove that restriction by slightly changing the code:

var obj = (function (baseModule, $) {
    var someValue = "private";
    function printValue(elemSelector) {
        $(elemSelector).text(someValue);
    }

    baseModule.printValue = printValue;
    return baseModule;
})(obj || {}, jQuery);
var obj = (function(baseModule, $) {
    var someOtherValue = "private 2";
    function printAnotherValue(elemSelector) {
        $(elemSelector).text(someOtherValue);
    }
    baseModule.printAnotherValue = printAnotherValue;
    return baseModule;
})(obj || {}, jQuery);

According to the standard, the operator || will return the first expression when it’s convertible to true. If that isn’t possible, then it will return the second expression. In my example, we can use an empty object ({}) to ensure that we’re always working with a valid object within the anonymous functions that define the module. Since there is no dependency between the files, then this is more than enough for removing the order dependency introduced by our first snippet.

Even though the previous snippet allows one method to call another (ie, if, for instance, we need to call printValue from within printAnotherValue at runtime, then we should be fine), if we need to access  properties in order to override them, then we’re out of luck . In these cases, we need to change the and there’s no way to escape the need to preserve the loading order. That will be the topic for another post. Stay tuned for more.

About these ads

~ by Luis Abreu on February 7, 2013.

2 Responses to “More about modules: augmentation”

  1. Why are you assigning the result of the IIFE to “obj”? It will get augmented internally, making the assignment redundant. Surely you’d do one or the other; use the return value or pass something in to be augmented? So if you were extending jQuery, you’d pass it in, augment it and forget about the return value.

    I’d also recommend adding ‘use strict’ to the beginning of each IIFE (http://stackoverflow.com/questions/1335851/what-does-use-strict-do-in-javascript-and-what-is-the-reasoning-behind-it) and referencing window.jQuery instead of just jQuery to satisfy JSHint.

  2. Hello Andrew.
    Sure. But with this strategy, I don’t need to worry about loading order and I know that obj will always be correctly initialized. You could also do what you’re saying: make sure obj is augmented and pass it around while ignoring the returned result.

    Regarding strict, you’re absolutely right and I use it most of the time (probably should have been explicit about it). On the window.jQuery vs jQuery, I’m still not convinced about its value (besides making jslint happy, that is).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 573 other followers

%d bloggers like this: