Search code examples
javascriptjqueryiife

Javascript Immediately-invoked function expression (IIFE) and function scoping


Please feel free to update the tittle to a more appropriate one. I was not sure how to word it.


So I have developed a habit (not sure if it is good or bad) of doing the following when I need to write jQuery for a site. I only use this on quick and dirty jobs where a single file is needed with few dependencies and AMD, RequireJS, and CommonJS are overkill. It is based off of this article by Greg Franko.

It keeps everything safe and non-conflicting and it does help with readability. Unfortunately though once I found it it became my go to template for all things jQuery, and I have never bothered to look into the performance impact of pitfalls of it.

That being said I would like to get some feedback on any issues that may arise with this technique, and specifically if I should use it or another technique.

When passed through JSLint I always get the following errors:

'a' was used before it was defined.
         $('#a').on('click', a);

Unused 'a'.
    function a() {

I know why the errors are there and what they mean, but I would like to have a passing JS file with my configuration options, and it works...

/*jslint browser: false, couch: false, devel: false, node: false, rhino: false, passfail: false, ass: false, bitwise: false, closure: false, continue: false, debug: false, eqeq: false, evil: false, forin: false, newcap: false, nomen: false, plusplus: false, regexp: false, unparam: false, sloppy: false, stupid: false, sub: false, todo: false, vars: false, white: false, indent: 4 */
/*global window, document, location, jQuery*/

(function (appLoad) {
    "use strict";
    appLoad(window.jQuery, window, document);
}(function ($, window, document) {
    "use strict";

    $(function () {

        // These are executed when the document is ready

        $('#a').on('click', a);
        $('#b').on('click', b);
        $('#c').on('click', c);

    });

    // Logic that is not dependent on the document being ready is below here.
    // I typically place all my logic functions here for readability.

    function a() {
      ...
    }

    function b() {
      ...
    }

    function c() {
      ...
    }
}));

Is there a better way of doing what I have illustrated?


Solution

  • JSLint is only complaining that your code looks like this:

    $(function() {
        $('#a').on('click', a);
    });
    
    function a() {
        // ...
    }
    

    Rather than:

    function a() {
        // ...
    }
    
    $(function() {
        $('#a').on('click', a);
    });
    

    So if you want to get rid of that warning, you could just move those functions around.

    That said, at the possible expense of clarity, you could rewrite

    (function (appLoad) {
        "use strict";
        appLoad(window.jQuery, window, document);
    }(function ($, window, document) {
        // ...
    }));
    

    as

    (function ($, window, document) {
        // ...
    }(window.jQuery, window, document));
    

    But that’s not what JSLint is complaining about.