3

I'm developing a jQuery application for a website and by what I have read, the module pattern seems to be the best setup.

I've begun to adapt the module/sub module pattern and before I write the application, I'm wondering if the development is correct. Here is a basic sample:

var module = (function($, window, document, undefined) {
    return {
        loader : (function() {

            var fade = 250; // public property
            var $loader = $('#loader'); // private property

            // return public properties and methods
            return {
                fade : fade,
                show : function() {
                    $loader.fadeIn(module.loader.fade);
                },
                hide : function() {
                    $loader.fadeOut(module.loader.fade);
                }
            }
        })()
    }
})(jQuery, window, document);
module.loader.fade = 500;
module.loader.show();

Again, "loader" would be a sub module. I want to keep all my sub modules wrapped in the main module.

I'm wondering if I'm handling the public property correctly, or if there is a better way?

Thanks

1
  • Yes it does. The function is anonymous and loads instantly. Commented Feb 11, 2014 at 16:31

3 Answers 3

2

Your IIFE is aware of the var module on line 1 because its show and hide methods are referencing module.loader.fade. That is not good. A properly written IIFE should have all dependencies passed in via arguments. In this example, if you changed the name of the variable from "module" to "module2", you'd have to change the body of your IIFE. A properly written IIFE does not have this problem.

You're also using a variant of the Revealing Module Pattern to expose the closure variable fade. I'm going to refrain from speaking ill of this widely accepted antipattern and simply point out two better alternatives below.

The first alternative uses this to reference the fade variable.

var module = (function($, window, document, undefined) {
return {
    loader : (function() {

        var fade = 250; // public property
        var $loader = $('#loader'); // private property

        // return public properties and methods
        return {
            fade : fade,
            show : function() {
                $loader.fadeIn(this.fade); // use this
            },
            hide : function() {
                $loader.fadeOut(this.fade); // use this
            }
        }
    })()
}
})(jQuery, window, document);
module.loader.fade = 500;
module.loader.show();

The second alternative creates a reference to the returned object.

var module = (function($, window, document, undefined) {
return {
    loader : (function() {

        var fade = 250; // public property
        var $loader = $('#loader'); // private property
        var stub;
        // return public properties and methods
        return stub = {
            fade : fade,
            show : function() {
                $loader.fadeIn(stub.fade); // use return object to reference fade
            },
            hide : function() {
                $loader.fadeOut(stub.fade); // use return object to reference fade
            }
        }
    })()
}
})(jQuery, window, document);
module.loader.fade = 500;
module.loader.show();
Sign up to request clarification or add additional context in comments.

2 Comments

to clarify -- are the alternatives used to avoid a situation where show and hide still references closure variable module.loader.fade if we've changed what the reveal object's fade exposes?
yes @ossek, that's the main reason for the alternatives (it's one of the major weaknesses of the Revealing Module Pattern). The other reason is to keep the IIFE self-contained -- it should not reference the module in its closure.
1

It looks like you'd be in the right to do it either way. This post suggests you can use a self-calling function for a sub-module: http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html#submodules. The only difference being that the submodule in this case is added following the creation of its parent module.

Another good overview of the module pattern and namespacing in general if you haven't stumbled on it yet: http://javascriptweblog.wordpress.com/2010/12/07/namespacing-in-javascript/. Of particular note are the idea that you can leave your context as a parameter for the Self-invoking function.

As an aside -- as your module and project architecture develop more, you might consider require.js for module management.

Comments

0

If your intention is to use:

module.loader.show();

I recommend getting rid of the self executing code in loader:

loader : function() {
    ...
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.