Module Pattern vs. Custom Objects

A little while ago I tried to gather together information about what kind of programming patterns are out there in the wild when it comes to JavaScript and describing the characteristics of each of those. At Yahoo!, the two patterns we use almost exclusively are Module Pattern (for functionality to be implemented on various properties) and Custom Objects (as in the YUI library, for example). The question I was asking myself is how they behave differently and whether you could do the same thing with both of them.

For this article I am sticking to the same simple example that I already used in my previous article. But to make it a little bit more interesting, we have two lists of links, not just one:

<ul id="list-1">
    <li><a href="http://news.bbc.co.uk/">News on BBC website</a></li>
    <li><a href="http://nytimes.com/">Frontpage of The New York Times</a></li>
    <li><a href="http://www.guardian.co.uk/">Guardian Unlimited</a></li>
</ul>

<ul id="list-2">
    <li><a href="http://valleywag.com/">Valleywag</a></li>
    <li><a href="http://techcrunch.com/">TechCrunch</a></li>
    <li><a href="http://www.yahoo.com/">Yahoo!</a></li>
</ul>

Clicking on one of the links should simply switch the background color to a value we would like to provide as a parameter. Essentially, we want to have two separate objects in the end that act independently from each other.

Custom Objects

The structure of the source code roughly remains the same as the one used in my previous article. The only difference is that I set up the constructor function in a way that it is possible to pass values to it (colors, Id of the list and some random value which we will use later to prove that we have two distinct objects).

function anchorChangerProto (colors, list, random) {
    this.config = {
        colors: colors,
        list: list
    }
    
    this.test = random;
}

No rocket science, pretty straight forward. I am also creating a logRandom() function which will log the value of test to the console.

anchorChangerProto.prototype.logRandom = function () {
    console.log(this.test);
}

Nothing unexpected in here either. So the full source code for anchorChangerProto looks like this:

function anchorChangerProto (colors, list, random) {
    this.config = {
        colors: colors,
        list: list
    }
    
    this.test = random;
}

anchorChangerProto.prototype.changeColor = function (linkObj, newColor) {
    linkObj.style.backgroundColor = newColor;
};

anchorChangerProto.prototype.init = function () {
    var self = this;

    // get all links from particular list
    var anchors = this.config.list.getElementsByTagName("a");
    var size = anchors.length;
    
    for (var i = 0; i < size; i++) {            
        anchors[i].color = self.config.colors[i];
        
        anchors[i].onclick = function () {
            self.changeColor(this, this.color);
            return false;
        };
    }
};

anchorChangerProto.prototype.logRandom = function () {
    console.log(this.test);
}

At the end of the page, in a <script> block I can now instantiate my objects and call their init methods.

var changer1 = new anchorChangerProto([ "#F63", "#CC0", "#CFF" ], document.getElementById("list-1"), "first changer");
changer1.init();
    
var changer2 = new anchorChangerProto([ "#009", "#990", "#909" ], document.getElementById("list-2"), "second changer");
changer2.init();

The new operator creates a generic object, sets its __proto__ value to anchorChangerProto.prototype, and passes that object to the constructor function as the this keyword. I tried to explain that in my other article about inheritance in JavaScript.

After these statements, we can call the logRandom function for each object to prove that we have indeed created two distinct objects which act independently from each other. Have a look at the demo page for this example.

changer1.logRandom(); // logs: "first changer"
changer2.logRandom(); // logs: "second changer"

Everything as expected. Now the question is whether the same thing can be achieved with the Module Pattern.

Module Pattern

It can be achieved, with some slight modifications. The main characteristics of the Module Pattern are that an anonymous function gets executed immediately and returns an object holding the publicly available properties for that object. In addition to that, you can also have private properties and methods, which can not be accessed from outside. So the basic structure is:

var myModule = function () {
    ... some private properties and methods ...
    return {
        ... some public properties and methods ...
    }
}();

The parens at the end ensure that the function gets called immediately, the object gets returned and assigned to the variable myModule. Now the first step to achieve the same thing as above is to remove those parens.

var myModule = function () {
    ... some private properties and methods ...
    return {
        ... some public properties and methods ...
    }
};

The reason for removing them is the following: If we keep them in there, myModule is always going to be the only one module of that kind on the page. The function will be executed, the object returned and assigned to the variable. You would not be able to create a distinctively different second object of that kind on the page.

However, by leaving out the parens at the end, we can simply call that function multiple times and always get a new object back which is unique. But not so fast. Before that I would like to show you the source code using the (slightly modified) Module Pattern:

var anchorChangerModule = function () {
    
    // private property
    var config = {};

    
    // this is a private method
    // can be accessed within anchorChange3
    // cannot be accessed from outside
    function alterColor(linkObj, color) {
        linkObj.style.backgroundColor = color;
    }

    return {
        // public method
        // can be accessed from outside
        changeColor: function (linkObj, newColor) {
            // calls private function to change color
            alterColor(linkObj, newColor);
        },
                    
        // public method
        // can be accessed from outside
        init: function (colors, list, random) {
            var self = this; // assign reference to current object to "self"
            
            config.colors = colors;
            this.test = random;
        
            // get all links on the page
            var anchors = list.getElementsByTagName("a");
            var size = anchors.length;
            
            for (var i = 0; i < size; i++) {
                anchors[i].color = config.colors[i];
                
                anchors[i].onclick = function () {
                    self.changeColor(this, this.color); // this is bound to the anchor object
                    return false;
                };
            }
        },
        
        logRandom: function () {
            console.log(this.test);
        }
    };
};

Again, nothing crazy going on here. As with the Custom Objects example above, I made sure that it is possible to pass in values to the init function and assign them to properties of the object and added the logRandom function. Now I can create the objects and the end of the page in a <script> block:

var changer1 = anchorChangerModule();
changer1.init([ "#F63", "#CC0", "#CFF" ], document.getElementById("list-1"), 'first changer');
    
var changer2 = anchorChangerModule();
changer2.init([ "#009", "#990", "#909" ], document.getElementById("list-2"), 'second changer');

What I am doing here, as opposed to above when using the new operator, is simply calling the anchorChangerModule function, which returns an object, which then gets assigned to changer1 and changer2, respectively. To prove again that we have indeed two distinct objects, let us call the logRandom function:

changer1.logRandom(); // logs "first changer"
changer2.logRandom(); // logs "second changer"

Again, we can clearly see that we have two different objects who operate independently from each other. And now, in fact, we have achieved the same thing as we did before with Custom Objects using the Module Pattern. The same thing? Well, not quite…

A Word about Inheritance

Taking a look at this simple example, yes, we have achieved the same functionality with both programming patterns. But the drawback is that if you strictly stick to the Module Pattern, no inheritance chain is being set up. You would not be able to create a sub-module of anchorChangerModule and make it inherit functionality from the parent. For this to work, you would need to use .prototype so that when calling a method, JavaScript will work its way up the inheritance chain using the __proto__ property of the object. As far as I know, this can only be done using .prototype and when instantiating a new instance of an object using the new operator.

But then again, I believe that the Module Pattern was not designed for setting up inheritance or replacing Custom Objects.

Feedback appreciated

I would not consider myself a JavaScript expert, by no means, therefor the conclusions I came up with which are stated above are just based on my own experiments and research. I would highly appreciate it if you guys could point out mistakes or flaws that I made in my conclusions and explanations, if you spot any. Thanks.