$(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);
view raw1.js hosted with ❤ by GitHub
vs
$(function(){
// Backbone code in here
});
view raw2.js hosted with ❤ by GitHub
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
});
view raw2.js hosted with ❤ by GitHub
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);
view raw1.js hosted with ❤ by GitHub
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();
});
view raw3.js hosted with ❤ by GitHub
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.

Comments

Popular Posts