$(function(){…}) vs (function($){…})($) or DOMReady vs The Module Pattern

This was originally a StackOverflow question. I’m re-posting here because I think the question is fairly common, and I like the answer that I provided. 

Why define anonymous function and pass it jQuery as the argument?

This is the original question title, but it doesn’t really show the nuances of the question’s content. The StackOverflow user really wants to know the difference between an immediately-invoked function expression, and the jQuery DOMReady event:

(function($) {
  // Backbone code in here
})(jQuery);

vs

$(function(){
  // Backbone code in here
});

At a high level, the two blocks of code shown are dramatically different in when and why they execute. They do not serve the same purpose. But they are not exclusive of each other. In fact, you can nest them in to each other if you want – although this can have some odd effects if you’re not careful.

jQuery’s “DOMReady” function

$(function(){
  // Backbone code in here
});

This is an alias to jQuery’s “DOMReady” function which executes when the DOM is ready to be manipulated by your JavaScript code. This allows you to write code that needs the DOM, knowing that the DOM is available and ready to be read, written to, and otherwise modified by your application. 

This is not a module, though. This is only a callback function passed in to the DOMReady alias. The major difference between a module and a callback, in this case, is that jQuery waits for the DOM to be ready and then calls the callback function at the appropriate time – all from the context of jQuery – while a module pattern or immediately invoking function executes immediately after it’s defined. In the above examples, the module is receiving jQuery as a parameter, but this is not the same as using jQuery’s DOMReady event because the module function is called, passing in jQuery as a parameter, immediately. It does not wait for the DOM to be ready. It executes as soon as the function has been parsed.

JavaScript Modules

(function($) {
  // Backbone code in here
})(jQuery);

This is an immediately-invoking function expression (FKA “anonymous function”, “self-invoking function”, etc).

The implementation of this is a function that is immediately invoked by the calling (jQuery) parenthesis. The purpose of passing jQuery in to the parenthesis is to provide local scoping to the global variable. This helps reduce the amount of overhead of looking up the $ variable, and allows better compression / optimization for minifiers in some cases.

In this case, the function is being used as the JavaScript “module” pattern. Modules in the currently implemented version of JavaScript in most browsers, are not specific constructs like functions. Rather, they are a pattern of implementation that use an immediately invoking function to provide scope and privacy around a “module” of related functionality. It’s common for modules to expose a public API – the “revealing module” pattern – by returning an object from the module’s function. But at times, modules are entirely self-contained and don’t provide any external methods to call. 

For more information on modules, see the following resources:

Modules vs DOMReady In Backbone Apps

It’s bad form to define your Backbone code inside of jQuery’s DOMReady function, and potentially damaging to your application performance. This function does not get called until the DOM has loaded and is ready to be manipulated. That means you’re waiting until the browser has parsed the DOM at least once before you are defining your objects.

It’s a better idea to define your Backbone objects outside of a DOMReady function. I, among many others, prefer to do this inside of a JavaScript Module pattern so that I can provide encapsulation and privacy for my code. I tend to use the “Revealing Module” pattern (see the links above) to provide access to the bits that I need outside of my module.

Modules And DOMReady In Backbone Apps

You’re likely going to use a DOMReady function even if you define your Backbone objects somewhere else. The reason is that many Backbone apps need to manipulate the DOM in some manner. To do this, you need to wait until the DOM is ready, therefore you need to use the DOMReady function to start your application after it has been defined.

Here’s a very basic example that uses both a Module and the DOMReady function in a Backbone application.

// Define "MyApp" as a revealing module

MyApp = (function(Backbone, $){

  var View = Backbone.View.extend({
    // do stuff here  
  });

  return {
    init: function(){
      var view = new View();
      $("#some-div").html(view.render().el);
    }
  };

})(Backbone, jQuery);



// Run "MyApp" in DOMReady

$(function(){
  MyApp.init();
});

Note that we’re defining the module well before the jQuery DOMReady function is called. We’re also calling the API that our module defined and returned from the module definition, within the DOMReady callback. This is an important point to understand, too. We’re not defining our objects and our application flow inside of the DOMReady callback. We’re defining it elsewhere. We’re letting the application definition live on it’s own. Then after the application has been defined, and when the DOM is ready, the application is started.

By defining your objects outside of the DOMReady function, and providing some way to reference them, you are allowing the browser to get a head start on processing your JavaScript, potentially speeding up the user experience. It also makes the code more flexible as you can move things around without having to worry about creating more DOMREady functions when you do move things.


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in Backbone, DOM, Javascript, JQuery, Principles and Patterns. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Anonymous

    You could, of course, wrap your document ready function in an immediately-executing function (IEF) so you can safely use the $ operator. In your example of  jQuery document ready with backbone code, why not wrap the whole thing in an IEF? It would be safer than your inconsistent use of $ and jQuery.

    I typically wrap all my code in an IEF, always, to avoid any pollution of the global space now or in future.

  • http://needforair.com/ Stanislas Marion

    I have the following problem with your proposed architecture: If I have a template that is defined as $(‘#myTemplate’).html(), it will be undefined.

    • http://mutedsolutions.com Derick Bailey

      you’re probably running in to a situation where you think the DOM is ready but it isn’t. using a module doesn’t negate the need to wait for the DOMReady event. you still have to wait for that before you can use a jquery selector.

      http://lostechies.com/derickbailey/2011/11/09/backbone-js-object-literals-views-events-jquery-and-el/

      if that doesn’t help, i suggest posting a question on http://stackoverflow.com and provide more code in the question, to outline what you’re trying to do

      • http://needforair.com/ Stanislas Marion

        yes, that was it. Actually I knew what the problem was, just didn’t think of putting the selector inside the initialize function. Thanks for your help!

  • getin

    How about this pattern :

    ( function($){ $( function($, undefined){ // code here } ) })(jQuery);

  • Fabio D’Amico

    Great! I’ve found your article quite useful! Many thanks.