Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IIFE inside $(document).ready or the other way around

My colleague has been extensively using IIFE inside (document).ready in his code. Now, I've read this post:

JQuery best practise, using $(document).ready inside an IIFE?

This got me thinking if we should use $(document).ready inside IIFE or is it also fine the other way around as my colleague is doing.

So basically, his code is setup like this:

jQuery(function() {
    (function($) {
        //...
        // Code here
        //...
    })(jQuery);
});

Is what he is doing generally fine?

like image 710
g_b Avatar asked Jul 26 '15 06:07

g_b


2 Answers

Some may argue that this is a matter of style/opinion, but if you consider the typical goal of an IIFE in that context I believe the answer is yes, it is acceptable to use your alternative way, but there is a potential drawback.

Wikipedia has to say that:

Immediately-invoked function expressions can be used to avoid variable hoisting from within blocks, protect against polluting the global environment and simultaneously allow public access to methods while retaining privacy for variables defined within the function.

Neither method pollutes the global namespace, because they don't declare any variables. Therefore, it should be fine to use either way. Although note that it is partially redundant because the function handler for the ready event already creates a new scope, and also note it is the most common practice to see IIFE functions encapsulate all of the code in a file.


One drawback to the way that your colleague is using: If you did want to do some javascript logic that didn't depend on the DOM being ready, then you would not have the benefits of the IIFE if you put your code outside of the IIFE. So something such as this would not be safe:

// Non-DOM-ready-required code here (NOT scope-safe)
jQuery(function() {
    (function($) {
        //...
        // DOM-ready-required code here
        //...
    })(jQuery);
});

Using the common style gives you the full IIFE benefit:

(function($) {
    // Non-DOM-ready-required code here (scope-safe)
    $(function() {
      //...
      // DOM-ready-required code here
      //...
    });
 })(jQuery);
like image 100
Chris Foster Avatar answered Sep 20 '22 15:09

Chris Foster


In my opinion, your colleague is jumping through an extra hoop for no reason. I'm going to ignore the outer $(document).ready as it's of no real consequence.

/*jQuery(*/function() {
    (function($) {
        //...
        // Code here
        //...
    })(jQuery);
}/*);*/

Using an IIFE as the entire body of the callback to jQuery confers no extra benefit in scope isolation. It's the same as if the code were

/*jQuery(*/function() {

        //...
        // Code here
        //...

});

The only thing that the IIFE has done is allow you to reference jQuery as $.

Now, if there were more substantive code inside the callback, then there could be some benefit in using an inner IIFE. In the following example, the callback contains two IIFEs,

jQuery(function() {
    // IIFE
    (function($) {
        //...
        // Code here
        //...
    })(jQuery);
    // IIFE 2
    (function($) {
        //...
        // Code here
        //...
    })(jQuery);
});

and the use of IIFE's allows scope isolation between the two blocks of code.

Back to the main question:

This got me thinking if we should use $(document).ready inside IIFE or is it also fine the other way around as my colleague is doing.

Now, to be honest, I don't understand why either of these should be regarded as a best practice, even after looking at your link. The people who answered never explained why it should be a best practice.

Looking at

(function($) {     
 $(document).ready(function() {   
    // other code here  
  });    
})(jQuery);

versus

//(function($) {     
 $(document).ready(function() {   
    // other code here  
  });    
//})(jQuery); 

There really isn't any significant advantage. Just as in my earlier example, the use of the IIFE offers no scope isolation advantage, and does nothing other than to allow you to reference jQuery via $.

However, in the actual linked question , the code looks like this:

(function($) {    
   // other code here 1
 $(document).ready(function() {   
    // other code here 2 
  });    
})(jQuery);

and in this case, the IIFE does serve a purpose of keeping the variables used in other code here 1 from leaking out to global scope. But this has nothing at all to do with $(document).ready(). Restructuring the code as

(function($) {    
   // other code here 1   
})(jQuery);

jQuery(document).ready(function() {   
   // other code here 2 
}); 

does the same thing.

The moral of this answer is that using an IIFE to wrap loose code that's not already inside a function gives you benefits, while wrapping code that's already inside a function doesn't give you anything (unless you count changing the reference).

like image 42
I-Lin Kuo Avatar answered Sep 23 '22 15:09

I-Lin Kuo