Search code examples
javascriptjquerydesign-patternsmodular

understanding a modular javascript pattern


I'm trying to write 'better' javascript.

Below is one pattern I've found, and am trying to adopt. However, I'm slightly confused about its use.

Say, for example, I've got a page called "Jobs". Any JS functionality on that page would be encapsulated in something like:

window.jobs = (function(jobs, $, undefined){
    return {
        addNew: function(){
            // job-adding code
        }
    }
})(window.jobs|| {}, jQuery);

$(function(){
    $('.add_job').on('click', function(event){
        event.preventDefault();
        window.jobs.addNew();
    });
});

As you can probably deduct, all I've done is replaced all the code that would have sat inside the anonymous event-handler function, with a call to a function in my global jobs object. I'm not sure why that's a good thing, other than it's reduced the possibility of variable collisions and made the whole thing a bit neater, but that's good enough for me.

The - probably fairly obvious - question is: all my event-binding init-type stuff is still sitting outside my shiny new jobs object: where should it be? Inside the jobs object? Inside the return object inside the jobs object? Inside an init() function?

I'm just trying to get a sense of a stable, basic framework for putting simple functionality in. I'm not building JS apps, I'd just like to write code that's a little more robust and maintainable than it is currently. Any and all suggestions are warmly welcomed :)


Solution

  • You can break down your application in whatever number of modules / objects you like too.

    For instance, you can have another object / module which caches and defines all your DOM nodes and another one, which just handles any event. So for instance:

    (function ( win, doc, $, undef ) {
        win.myApp = win.myApp || { };
    
        var eventHandler = {
            onJobClick: function( event ) {
                event.preventDefault();
                myApp.addNew();
            }
        };
    
        var nodes = (function() {
            var rootNode = $( '.myRootNode' ),
                addJob = rootNode.find( '.add_job' );
    
            return {
                rootNode: rootNode,
                addJob: addJob
            };
        }());
    
        $(function() {
            myApp.nodes.addJob.on( 'click', myApp.handler.onJobClick );
        });
    
        myApp.nodes = nodes;
        myApp.handler = eventHandler;
    }( this, this.document, jQuery ));
    

    It doesn't really matter how you create singletons in this (module) pattern, either as literal, constructor, Object.create() or whatnot. It needs to fit your requirements.

    But you should try to create as many specific modules/objects as necesarry. Of course, if makes even more sense to separate those singletons / modules / objects into multiple javascript files and load them on demand and before you can say knife, you're in the world of modular programming patterns, dealing with requireJS and AMD or CommonJS modules.