DEV Community

Cover image for IIFE... Excuse me, what?
guennithegun
guennithegun

Posted on

IIFE... Excuse me, what?

Since the first time I read about IIFE, I could not forget this abbreviation. Iffy...

IIFE stands for immediately invoked function expression. It is a JavaScript function that runs as soon as it is defined. It is a design pattern which is also known as a self executing anonymous function.

The syntax looks like this:

  // IIFE
  (function(){
    // do something here
  })();

So what do we have here? Let's go into details. The IIFE contains two major parts.

anonymous function

The first part is the anonymous function with lexical scope:

  // I am anonymous
  function(){
    // do something here
  };

Hold on a minute what is lexical scope? Check this article for some details on that topic: I would try to explain lexical scope in plain English. Wish me luck.

An anonymous function is a function that was declared without any named identifier to refer to it. It is usually not accessible after its initial creation.

  // normal function definition
  function hello() {
    console.log('A is A');
  };

  hello(); // output 'A is A'

  // anonymous function definition
  function(){
    // do something
  });

A common use for anonymous functions is for example as argument to another function.

  // example
  setTimeout(function() {
    alert('I am John Galt.');
  }, 1000);

In the IIFE the anonymous function is enclosed within the grouping operator ().

direct interpretation of the function

The second part creates the immediately invoked function expression () through which the JavaScript engine will directly interpret the function. The difference to the normal function definition is that with IIFE, declaration and execution are performed at the same time. With the normal function definition you first declare the function and then call it, placing the parentheses after it to indicate that you want to execute it.

why use IIFE?

Ok, so now we know a bit more about the syntax. But what is the benefit of IIFE?

It is about scope. In JavaScript variables declared outside of a function are global variables. Functions declared inside of a function are called local variables.

A global variable can be accessed from anywhere in your code. This comes with some downsides like

  • you can (accidentally) access the global state, which leads to impure functions
  • you can overwrite other global variables

Imagine you have two JavaScript files and each contains var johnGalt = {}; The variable johnGalt would be global and therefore shared in all code and executed no matter in which file it was written.

To prevent this the IIFE pattern exists. When you wrap all your global variables into IIFE you take them their globalness. You can treat them as local variables within the IIFE as they are wrapped into a function. The variables within the expression can not be accessed from outside.

  (function() {
    var johnGalt = 'Who is';
  })();

  // variable can not be accessed
  console.log(johnGalt); // Uncaught ReferenceError: johnGalt is not defined

When you need access to the global variables inside the IIFE you can do something like this:

  var galtsGulch = (function() {
    var johnGalt = 'Who is';
    return johnGalt;
  })();

  console.log(galtsGulch); // output 'Who is'

If you assign the IIFE to a variable it does not store the function definition but its return value. So everything which is returned by the IIFE function is accessible from outside. This allows you to control what should be globally accessible and what should not.

You can also do some cool stuff and manipulate your global variables inside IIFE. You can do that like this:

  var galtsGulch = (function() {
    var residents = []; // empty array

    return {
      // add a resident
      add: function(resident) {
        residents.push(resident);
      },
      // get all residents
      getAll: function() {
        return residents;
      }
    };
  })();

  console.log(galtsGulch.getAll()); // []
  galtsGulch.add({ name: 'John Galt' });
  console.log(galtsGulch.getAll()); // [ Object { name: 'John Galt' } ]

Here the IIFE returns an object with the two keys add and getAll. So whenever you access galtsGulch it represents an object with these two keys. The two keys hold functions that allow you to interact with the residents variable from outside. add adds a resident to the array and getAll gets the complete 'residents' variable.

COOL!

conclusion

With the IIFE pattern it is nearly impossible to accidentally modify or access the shared state. That’s why this pattern is so useful, why it’s commonly used in many applications, and why you should use it, too!

Top comments (2)

Collapse
 
ahferroin7 profile image
Austin S. Hemmelgarn • Edited

Fun fact: Because of how ES6 class definitions work, you can use the same type of syntax as an IIFE for a class definition like so:

let foo = new (class bar {
    /* Put class body here... */
})()

This, in turn, is useful for cases where it's much clearer what's going on in an object that you only need a single instance of when it's written out as a class than as an object literal, but you don't want to have to deal with the constructor being in the namespace (local or global). I've seen it used sometimes for constructing default exports for ES6 modules that implement state machines or similar constructs where you need to encapsulate state as part of the module itself.

This works because an ES6 class declaration is an expression that evaluates to the constructor function for the class itself, which you can then immediately invoke (but don't forget the new, otherwise you'll get weird behavior).

Collapse
 
guennithegun profile image
guennithegun

Hi Austin,

cool! Thanks for sharing this additional input here!