Search code examples
closuresmodule-patternjavascript

Javascript Module Using Apply and Returning This


I have been in constant search for the most simple Javascript module pattern. I have read pretty much every article I can find. Most module patterns like to create an object, add functions to it, then return that object and expose the public methods, like this:

var Module = (function() {
    var exports = {}, x = 1;

    function private() {
        return x;
    }

    exports.public = function() {
        return x;
    };

    return exports;
}());

This seems like over the long term it may be a pain, so I was looking for an easier way. I've seen that I can call apply to the function, and pass in an object, then use "this" to reference it and return "this" for the same effect, like this:

var Module = (function() {
    var x = 1;

    function private() {
        return x;
    }

    this.public = function() {
        return x;
    };

    return this;
}).apply({});

Is there anything wrong with using apply and passing in an empty object? This seems like the best way as the "this" keyword goes nicely with JS Intellisense coloring, and seems to be easier to understand. Anybody see any problems with this or have a simpler way?


Solution

  • This seems like the best way as the "this" keyword goes nicely with JS Intellisense coloring

    That really shouldn't be an argument for anything :-)

    seems to be easier to understand.

    Not to me, actually. this is typically used in constructors and in object methods only, not in IEFEs (unless it refers to the same as this outside of the IEFE, i.e. the global object). So to understand what you are doing here, I'd have to scroll down to the end of the file to find out how the function is called.

    Anybody see any problems with this

    Yes. Apart from being unusual, it deprives you of a static, local reference to your module object. If you want to call one of your public methods from somewhere in your module, you can use this (inside other public methods) or Module, but neither of them works the same as exports.

    or have a simpler way?

    You could also mix the two patterns:

    var Module = (function(exports) {
        var x = 1;
    
        function private() {
            return x;
        }
    
        exports.public = function() {
            return x;
        };
    
        return exports;
    }({}));