Creating Multiple JavaScript Objects when using the Revealing Module Pattern

In my previous series on Techniques, Strategies and Patterns for Structuring JavaScript Code I discussed the Revealing Module Pattern and explained how it provides a great way to structure JavaScript code while allowing members of an object to be made public or private. After the post went live an excellent question was asked in the comments section that I thought I’d address with a follow-up post:

"Can the Revealing Module Pattern pattern handle multiple instances on a page? With the prototype pattern, you just new up as many instances as you need. But - based on your example - the Revealing Module Pattern pattern looks more like a static class where you are limited to one instance on a page."

The question was based on the following Calculator object shown in the original post:

var Calculator = function () {
    var eqCtl,
    currNumberCtl,
    operator,
    operatorSet = false,
    equalsPressed = false,
    lastNumber = null,

    init = function (equals, currNumber) {
        eqCtl = equals;
        currNumberCtl = currNumber;
    },

    add = function (x, y) {
        return x + y;
    },

    subtract = function (x, y) {
        return x - y;
    },

    multiply = function (x, y) {
        return x * y;
    },

    divide = function (x, y) {
        if (y == 0) {
            alert("Can't divide by 0");
            return 0;
        }
        return x / y;
    },

    setVal = function (val) {
        currNumberCtl.innerHTML = val;
    },

    setEquation = function(val) {
        eqCtl.innerHTML = val;
    },

    clearNumbers = function() {
        lastNumber = null;
        equalsPressed = operatorSet = false;
        setVal('0');
        setEquation('');
    },

    setOperator = function(newOperator) {
        if (newOperator == '=') {
            equalsPressed = true;
            calculate();
            setEquation('');
            return;
        }

        //Handle case where = was pressed
        //followed by an operator (+, -, *, /)
        if (!equalsPressed) calculate();
        equalsPressed = false;
        operator = newOperator;
        operatorSet = true;
        lastNumber = parseFloat(currNumberCtl.innerHTML);
        var eqText = (eqCtl.innerHTML == '') ?
            lastNumber + ' ' + operator + ' ' :
            eqCtl.innerHTML + ' ' + operator + ' ';
        setEquation(eqText);
    },

    numberClick = function(e) {
        var button = (e.target) ? e.target : e.srcElement;
        if (operatorSet == true || currNumberCtl.innerHTML == '0') {
            setVal('');
            operatorSet = false;
        }
        setVal(currNumberCtl.innerHTML + button.innerHTML);
        setEquation(eqCtl.innerHTML + button.innerHTML);
    },

    calculate = function() {
        if (!operator || lastNumber == null) return;
        var currNumber = parseFloat(currNumberCtl.innerHTML),
            newVal = 0;
        //eval() would've made this a whole lot simpler
        //but didn't want to use it in favor of a more
        //"robust" set of methods to demo patterns
        switch (operator) {
        case '+':
            newVal = add(lastNumber, currNumber);
            break;
        case '-':
            newVal = subtract(lastNumber, currNumber);
            break;
        case '*':
            newVal = multiply(lastNumber, currNumber);
            break;
        case '/':
            newVal = divide(lastNumber, currNumber);
            break;
        }
        setVal(newVal);
        lastNumber = newVal;
    };

    return {
        init: init,
        numberClick: numberClick,
        setOperator: setOperator,
        clearNumbers: clearNumbers
    };
} ();


When the Calculator code is initially parsed the function assigned to the Calculator variable is invoked right away which creates one object in memory as the question infers. This is done by adding parenthesis immediately after the function definition. But, what if you’d like to create and use multiple calculator objects on a single page? There’s another technique that can be used with the Revealing Module Pattern if/when multiple objects need to be created in a page or script. This is done by removing the final parenthesis in the code above and calling the Calculator object as shown next:


var myCalc;
window.onload = function () {
    var eqCtl = document.getElementById('eq');
    var currNumberCtl = document.getElementById('currNumber');
    myCalc = Calculator(); //Invoke the object (function assigned to the object) and assign to myCalc
    myCalc.init(eqCtl, currNumberCtl);
};

Once the Calculator function is invoked and assigned to the myCalc variable, the public functions exposed by Calculator can be called through myCalc. For example, the previous code uses myCalc to call the Calculator object’s init() function. Note that the myCalc variable is defined outside of onload in this case so that it can be accessed elsewhere in the script or within an HTML page if needed.

Different variables can be assigned to the call to Calculator() following this same pattern if multiple objects are needed in a page or script. Keep in mind that each call to Calculator() places a new copy of each function in memory, but the impact is quite minimal in this case. If you’re worried about multiple copies of functions being placed in memory as objects are created then consider using the Revealing Prototype Pattern since it leverages JavaScript prototyping.

Thanks to Roger for asking a great question!



Pluralsight Course - Structuring JavaScript Code in HTML5 Applications

If you're interested in additional information about structuring JavaScript code check out my Pluralsight course. Here's a sample from the course covering closures.

Demo - Working with Closures in JavaScript




comments powered by Disqus

4 Comments

Comments have been disabled for this content.