15

I've been using IIFE in JavaScript and in AngularJS and have been using the following structure:

Method 1:

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


}());

However, I've seen the following often where a variable is assigned to the IIFE

Method 2:

//IIFE Immediately Invoked Function Expression assigned to doStuff variable
var doStuff = (function () {


}());

NOTE: This question is NOT about what this pattern is or what an IIFE is. This is pertaining specifically to why one would use a return variable on an IIFE and its relation to Angular practices as well.

In Angular Method 1 works fine, but in many of the raw JS examples I see, Method 2 is used. My assumption is that anything encasulated in doStuff will be avliable via it and callable. However, I'm not 100% sure on the exact reasoning or distinction between the 2 methods and need some help understanding when to use the different methods?

atconway
  • 20,624
  • 30
  • 159
  • 229
  • @Bergi - This isn't a duplicate - please READ the question and see the difference from the link supposedly a duplicate. That link does not answer this question. – atconway Oct 19 '14 at 15:53
  • 2
    I'm not sure I understand the question. You seem to know what an IIFE does; now why would one use a return from an IIFE? Whenever you *want* a `return` from the expression to assign the value to `doStuff`; instead of just executing a void IIFE. If you're looking for use cases, you should google for "module pattern", because that's what an IIFE with a return value is called. – Bergi Oct 19 '14 at 15:59
  • @Bergi - I believe the comment you just posted is actually a good explanation to what I posted and what I would call, 'an answer'. If you re-open and post that blurb as an answer I'll upvote. Don't forget, just because something is obvious to you does not mean it is to the OP (me). Also because it is obvious is not grounds for closing either. I needed specific examples and an explanation of why the return variable vs. not using. In `Angular` they don't have return variables all the time, yet many JS examples _do_ use a return. I want to know and understand 'why'. – atconway Oct 19 '14 at 16:06
  • 2
    This is the second time I've seen the name IIFE harm understanding. If we were to call this design pattern using it's old/traditional name - "self calling function" - the reason why some are assigned to a variable and some aren't wouldn't be mysterious: because that's what functions do. Some functions return values that you use some functions don't. If people insist that self calling function is wrong then at least call it immediately invoked function expression. Just don't call it IIFE - people forget that IIFE are nothing special/magical - they're just functions. – slebetman Oct 19 '14 at 17:07
  • @slebetman - I think what I was trying to get at from the `Angular` perspective is _why_ we can have void return `IIFE`s, but yet still have publically available functions returned and available? I was looking for validation that the `Angular` module container where the controller being wrapped in an `IIFE` was the reason we could still access those functions within the `IIFE` that does not itself contain a return variable. However the controller itself does have a return variable and it is registered when using `app.controller`. – atconway Oct 20 '14 at 15:02

1 Answers1

17

The reason for Method #2 is that you'll find code within the IIFE that returns something (typically, but not necessarily, an object or a function). What the IIFE returns is what ends up being assigned. E.g.:

//IIFE Immediately Invoked Function Expression assigned to doStuff variable
var doStuff = (function () {
    var privateInformationForDoStuff = 0;

    function doStuff() {
        console.log(++privateInformationForDoStuff);
    }

    return doStuff;
}());

There, the variable ends up being a reference to a function that, each time it's called, gives us a number higher than the previous time. The IIFE is there to ensure that nothing can modify the privateInformationForDoStuff variable, it's entirely private to the doStuff function.

It was common to use this (sometimes called the "revealing module pattern") to create objects with various functions on them which might also have private information that's only shared within the "module":

var MyApp = (function() {
    var privateModuleInformation;
    var morePrivateModuleInformation;
    // ...

    function doThis() {
        // ...
    }

    function doThat() {
        // ...
    }

    function doTheOther() {
        // ...
    }

    return {
        doThis: doThis,
        doThat: doThat,
        doTheOther: doTheOther
    };
})();

In modern environments you'd use an actual module instead, but that didn't used to be an option.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 2
    This helps a lot thank you. I think the gap is why `AngularJS` doesn't require assigning a variable to the `IIFE` created for controllers, services, etc. I believe the reason it doesn't require them is because inside the `IIFE` the code registers itself with the Angular module container used via the `ng-app` directive thus giving access to everything returned from the `IIFE` without the use of a return variable. Do you know this to be a true explanation? – atconway Oct 19 '14 at 15:06
  • 1
    @atconway: Probably. You see IIFEs that don't return values in non-Angular code as well. For instance, here's my usual polyfill for browsers that don't have `String#trim` natively (yet): http://pastie.org/9660901 (it's usually part of something larger, of course). – T.J. Crowder Oct 19 '14 at 15:08
  • 1
    Via your examples in this post above, I'm assuming the variables `doStuff` and `myApp` would be for use in the _same_ .js file to reference and not in other files? Or is it common practice for those return variables to be used publicly across multiple .js files? – atconway Oct 19 '14 at 15:16
  • 2
    @atconway: If the code above is at global scope, those would be global variables, and so could be used by other JavaScript loaded in the same window. If the code above is not at global scope, they aren't globals, and so they probably can't be. I try to avoid creating any globals in my code; you might look at the various AMD (Asynchronous Module Definition) mechanisms for loading multiple scripts that depend on each other. – T.J. Crowder Oct 19 '14 at 15:18
  • Ok I think some light bulbs are coming on now - In `AngularJS` the 'glue' for connecting `IIFE`s is the framework itself and the module associated with. In raw JS, the 'glue' is through global script tags providing access if needed. Then there is also alternate methods like `AMD` which clean up dependencies and provide multiple means to provide the 'glue' to each of the files or globally exposed values.by defining how they are related. – atconway Oct 19 '14 at 15:43