Instant Invokation Patterns

Immediately-Invoked Functions (IIFE)

Todd Motto by Todd Motto Google Developer Expert Icon Google Developer Expert
JavaScript Icon

Learn JavaScript the right way

Premium JavaScript courses to skyrocket your skills to the top.

5x Courses: Basics, Masterclass, HTML5 APIs, DOM, Testing with Jest.

Immediately Invoked Function Expressions (IIFEs) are functions that run immediately after being defined.

They differ to creating named functions and invoking them, and have several clever use-cases.

Typically they are used to emulate a “private” scope for your code, where we want to protect contents of a program.

First, let’s take a look at an IIFE then demonstrate some use cases. To create an expression in JavaScript we wrap code inside parenthesis ().

We can do the same with functions:

(function() {});

This uses an anonymous function and wraps it in an expression. Why? It doesn’t do anything at this point, until we invoke the function.

To do this, we call the function using ():

(function() {})();

We can also opt for arrow functions:

(() => {})();

IIFEs are great for enclosing the contents of, for example, a compiled module of code. Think third-party libraries.

Using an IIFE means that we don’t pollute the global namespace with variables and functions, they remain “private” and inaccessible to developers - giving us the flexibility to make variables public if we wish.

A great example of this is building code that runs in the browser, where all code is wrapped inside an IIFE for protection:

(() => {
  const form = document.forms.drinks;

  const handleSubmit = (e) => {};

  form.addEventListener('submit', handleSubmit);
})();

All code inside the IIFE remains “private” and is not accessible publicly.

What’s more, is we can pass variables into the IIFE that will optimize our production-ready code by aiding minification:

((d) => {
  const form = d.forms.drinks;

  const handleSubmit = (e) => {};

  form.addEventListener('submit', handleSubmit);
})(document);

Notice how document is passed as an argument, and d is used throughout the function. Across larger codebases this saves many bytes of code and is a common technique with minification.

IIFEs can also be used to initiate the values of variables, whilst encapsulating any behavior you wish to add:

const mappedDrinks = ((drinks) => {
  const timestamp = Date.now();

  return drinks.map(drink => {
    return {
      ...drink,
      timestamp
    };
  })
})(loadedDrinks);

// Array [{ name: 'Lemonade', timestamp: 1654942091573 }]
console.log(mappedDrinks);

Note how timestamp is created within the IIFE, and assigned to each drink. It allows us to create variables inside a unit of code and keep the logic clean.

This is a contrived example but offers you insight into the flexibility and power of using IIFEs.

In the real-world, you’ll often find code like Angular, React, Vue and many more all wrapping code in IIFEs on the top level, as well any lazy-loaded modules.

Tooling libraries such as TypeScript and Babel will also transform your code to using them.

A community project named UMD (Universal Module Definitions) popularised this pattern.

Here’s an example that allows your code to be written to support multiple formats - it implements all the concepts we’ve discussed above:

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['b'], function (b) {
            // Also create a global in case some scripts
            // that are loaded still are looking for
            // a global even when an AMD loader is in use.
            return (root.amdWebGlobal = factory(b));
        });
    } else {
        // Browser globals
        root.amdWebGlobal = factory(root.b);
    }
}(typeof self !== 'undefined' ? self : this, function (b) {
    // Use b in some fashion.

    // Just return a value to define the module export.
    // This example returns an object, but the module
    // can return a function as the exported value.
    return {};
}));

With this in mind, you’re fully equipped to take on more advanced JavaScript challenges and use cases.

Operations On Functions

« Higher Order Functions

Predictable and Testable

Pure versus Impure Functions »