jQuery best practices in case of $('document').ready

17.7k views Asked by At

I was researching on jQuery best practices and found this article by Greg Franko

Normally, I do:

$("document").ready(function() {
    // The DOM is ready!
    // The rest of the code goes here
});

But the article recommends to use:

// IIFE - Immediately Invoked Function Expression
(function($, window, document) {

    // The $ is now locally scoped 

    // Listen for the jQuery ready event on the document
    $(function() {

        // The DOM is ready!

    });

    // The rest of the code goes here!

}(window.jQuery, window, document));
// The global jQuery object is passed as a parameter

I can see the comments there, but I couldn't figure out what it exactly saying.

So, which is the better approach and why?

I know that both methods will work, but how does the second one become the better?

9

There are 9 answers

5
Greg Franko On BEST ANSWER

Immediately Invoked Function Expressions (IIFEs)

IIFEs are an ideal solution for locally scoping global variables/properties and protecting your JavaScript codebase from outside interference (e.g. third-party libraries). If you are writing jQuery code that will be run in many different environments (e.g. jQuery plugins), then it is important to use an IIFE to locally scope jQuery because you can’t assume everyone is using the $ to alias jQuery. Here is how you would do it:

   // IIFE - Immediately Invoked Function Expression
  (function($, window, document) {
      // The $ is now locally scoped

      // The rest of your code goes here!

  }(window.jQuery, window, document));
  // The global jQuery object is passed as a parameter

If you don’t like having to scroll to the bottom of your source file to see what global variables/properties you are passing to your IIFE, you can do this:

   // IIFE - Immediately Invoked Function Expression
  (function(yourcode) {

      // The global jQuery object is passed as a parameter
      yourcode(window.jQuery, window, document);

      }(function($, window, document) {

          // The rest of your code goes here!

      }
  ));

To read more about IIFEs, you can read my blog post titled, I Love My IIFE.

jQuery Ready Event

Many developers wrap all of their code inside of the jQuery ready event like this:

   $("document").ready(function() {
      // The DOM is ready!
      // The rest of your code goes here!
  });

Or a shorter version like this:

   $(function() {
      // The DOM is ready!
      // The rest of your code goes here!
  });

If you are doing either of the above patterns, then you should consider moving the pieces of your application (e.g. methods), that don’t depend on the DOM, outside of the ready event handler. Like this:

   // IIFE - Immediately Invoked Function Expression
  (function(yourcode) {

      // The global jQuery object is passed as a parameter
      yourcode(window.jQuery, window, document);

      }(function($, window, document) {

          // The $ is now locally scoped 
          $(function() {

              // The DOM is ready!

          });

          // The rest of your code goes here!

      }
  ));

This pattern makes it easier to separate your logic (from a code design perspective) since not everything has to be wrapped inside of a single event handler callback function. It will also improve your application’s page load performance, since not everything needs to initialized right away. A great example of this is lazy binding DOM event handlers that do not need to be bound when the DOM is ready.

Adapted from my jQuery Best Practices blog post: http://gregfranko.com/blog/jquery-best-practices/

0
Maciej Gurban On

In the rare situation when you'll have to work on an older jQuery version (if I recall correctly - pre 1.8.X), whenever you'd specify two document.ready blocks, only the first one would be fired in IE9.

Now this is a rare bug I experienced once, or twice and which I fail to be able to reproduce, but I thought it would be worth noting.

2
rderoldan1 On

Based in Jquery documentation:

All three of the following syntaxes are equivalent:

$(document).ready(handler)
$().ready(handler) (this is not recommended)
$(handler)

http://api.jquery.com/ready/

4
dwerner On
  1. $(function(){}) is equivalent to $('document').ready(function(){});. It's up to you which you use, but the latter is the older of the two, and more verbose to boot.

  2. The second approach you have listed is an explicit attempt to prevent global variables, and injects the known globals $, window, and document. This is recommended to increase awareness of how easily globals are introduced, and be as 'clean-room' as possible about the code we are injecting to the page. Also, note that the second approach is not equivalent to the first if you follow the comments shown. Because $ is inserted as an argument, this code is compatible with other libraries that may desire to own the $ symbol.

In particular, // The rest of the code goes here is in a place that may be executed before the document is ready, or when that event is fired. Put it inside the function passed to $.

3
Balaji Kandasamy On

Your link has the anwser:

The below is fine,

If you know the environments where your code will run.

If you do not care about page load performance.

If you don't care about best practices.

 $("document").ready(function() {
    // The DOM is ready!
    // The rest of the code goes here
  });

But they recommend, its better to use like below for, If you don't know the environment where your code will run and

Better page load performance

// IIFE - Immediately Invoked Function Expression
  (function($, window, document) {

    // The $ is now locally scoped 

   // Listen for the jQuery ready event on the document
   $(function() {

     // The DOM is ready!

   });

   // The rest of the code goes here!

  }(window.jQuery, window, document));
  // The global jQuery object is passed as a parameter
0
palerdot On

If you use $ as an alias for jQuery then

   $(document).ready(function(){})

is same as

  (function($, window, document) {

  // The $ is now locally scoped 

 // Listen for the jQuery ready event on the document
  $(function() {

    // The DOM is ready!

  });

  // The rest of the code goes here!

 }(window.jQuery, window, document));

As pointed out in an earlier answer, the second method insulates you from using $ alias freely for jQuery as it passes the jQuery object to the Immediately invoked function expression, which basically keeps the variables and code within it private, and does not pollute the global namespace.

In short, if you resort to the first method and use other libraries using $, you will end with conflict.

3
Blender On

The only difference between your code and the "suggested" approach is compatibility and possibly better compression. There are no speed differences.

Passing window.jQuery as the first argument to your IIFE (immediately-invoked function expression) and naming it $ within the IIFE will just allow you to use jQuery without interfering with other libraries that assign themselves to the global $. If you don't use any other libraries that assign themselves to the global $, the first argument to your IIFE isn't going to serve any purpose.

Passing window and document to your IIFE will allow JS minifiers to transform your code into something like this (without the whitespace), which gives you slightly better compression:

(function(a, b, c) {
    a(c).ready(function() {
        // ...
    });
})(window.jQuery, window, document);

Unless you use window and document extensively, I would just do:

;(function($) {
    $(function() {
        ...
    });
})(jQuery);
0
Rohan Kumar On

It's called a self ivoking or immediately invoked function. It means that the function is run as soon as it is created using the parameters in the final set of brackets.

Read Javascript Self Invoking Functions and Immediately-Invoked Function Expression (IIFE) will clear where to use and how to use these functions

0
Nimesh khatri On

You can use document ready event using jquery, event occure when document is fully loaded.

 $(function () {
    setTimeout(function () {
        // your code
    }, 0);
})