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




Published Monday, September 5, 2011 8:54 PM by dwahlin

Comments

# re: Creating Multiple JavaScript Objects when using the Revealing Module Pattern

Tuesday, September 6, 2011 12:28 PM by JB

Great tip. Thanks!

# re: Creating Multiple JavaScript Objects when using the Revealing Module Pattern

Tuesday, September 6, 2011 1:35 PM by Roger Martin

Excellent - thanks for following up. Now I need to figure out which pattern I like better as I refactor all the javascript in Gallery Server Pro.

# re: Creating Multiple JavaScript Objects when using the Revealing Module Pattern

Tuesday, September 6, 2011 6:02 PM by dwahlin

Roger: No problem...thanks for the question. Let me know what pattern you decide to use. My personal favorite is currently the Revealing Module Pattern although I prefer using the "new" keyword to create objects like with the other patterns. Aside from that, I like what it offers overall. But, I'm always on the lookout for other options. :-)

Dan

# re: Creating Multiple JavaScript Objects when using the Revealing Module Pattern

Wednesday, September 7, 2011 7:23 AM by Ruslan

Good stuff. I was about to start using the prototype (revealing prototype) pattern as I thought this one doesn't allow to handle multiple instances. Thanks.

# Techniques, Strategies and Patterns for Structuring JavaScript Code

Sunday, September 1, 2013 2:16 PM by Dan Wahlin

JavaScript has come a long way since the mid-90s when I first started working with it in Netscape 3 and