Tutorials Books Videos Forums

Change the theme! Search!
Rambo ftw!

Customize Theme


Color

Background


Done

Immediately Invoked Function Expressions (aka IIFE)

by kirupa   |   filed under JavaScript 101

We are going to take a slight detour from our (nearly finished) coverage of objects to focus on something important that can only properly make sense at this point. You’ll see why in a few moments when we walk through some examples. Anyway, getting back on track. By now, you probably know enough about functions in JavaScript to be dangerously productive. Functions allow you to group statements together. If you give your function a name, you can re-use those grouped statements a whole bunch of times:

function areYouLucky() {
    var foo = Math.round(Math.random() * 100);
    
    if (foo > 50) {
        alert("You are lucky!");
    } else {
        alert("You are not lucky!");  
    }
}

// calling this function!
areYouLucky();

If you don't give your functions a name, that is totally cool as well. They are known as anonymous functions, and they look as follows:

// anonymous function #1
var isLucky = function() {
    var foo = Math.round(Math.random() * 100);
    
    if (foo > 50) {
        return "You are lucky!";
    } else {
        return "You are not lucky!";
    }
};

var me = isLucky();
alert(me);


// anonymous function #2
window.setTimeout(function() {
    alert("Everything is awesome!!!");
}, 2000);

These anonymous functions can only be called if they are associated with a variable as shown in the first example. They can also be called if they are provided as part of another function (such as setTimeOut) that knows what to do with them.

In this article, we are going to look at another function letiation known as an Immediately Invoked Function Expression. Friends like us just call it IIFE (pronounced "iffy"). At first, what it does might seem a bit boring and unnecessary. As we get more familiar with it, I will describe some of its use cases and why you may find yourself both seeing and using these IIFEs a whole lot. By the end, IIFEs will probably still be very boring, but at least they will seem quite useful and necessary...hopefully!

Onwards!

Writing a Simple IIFE

To be very blunt, an IIFE is nothing more than a function surrounded by a whole bunch of parenthesis that executes immediately. Before we do anything else, let's just write an IIFE and prove to ourselves that it actually does whatever it is supposed to do. Below is a simple IIFE:

(function() {
    var shout = "I AM ALIVE!!!";
    alert(shout);
})();

Go ahead and add these few lines of code and preview it in your browser. If everything worked properly, you will see I AM ALIVE!!! displayed. If things didn't work properly and you don't see that, make sure your many parentheses are in the correct locations. The most common illness that afflicts IIFEs are mismatched or misplaced parentheses! Anyway, now that you have created a working IIFE, let’s peel back the layers and look at what exactly is going on.

First, you have your function with the code you want to execute:

function() {
	var shout = "I AM ALIVE!!!";
	alert(shout);
}

This is just a simple anonymous function that displays some obnoxious all-caps text. As this function stands, though, JavaScript has no idea what to do with it. This function is invalid syntax. To get it more valid, add the () after the function body:

function() {
	var shout = "I AM ALIVE!!!";
	alert(shout);
}()

Adding the () generally means you intend for whatever preceded the () to execute immediately. When you do this, JavaScript will still complain because this is also not valid syntax. The reason is that you need to tell JavaScript that this function you want to execute is actually an expression. The easiest way to do that is to wrap your function inside another pair of parentheses:

(function() {
    var shout = "I AM ALIVE!!!";
    alert(shout);
})();

Your entire function is now treated as an expression. Following this with the () you saw a few moments ago allows your function expression to be executed. You could say that this function expression gets executed (aka invoked) almost immediately once JavaScript encounters it.

Writing an IIFE that Takes Arguments

At first, the most difficult thing to grasp about IIFE's is that they are nothing more than simple functions. These simple functions just happen to wear all sorts of crazy parentheses to help them execute immediately. Despite that, there are some minor differences in how you work with IIFEs. Once major minor difference is how you deal with passing in arguments, and so let's address that next!

The general structure for creating an IIFE that takes arguments is as follows:

(function(a, b) {
    /* code */
})(arg1, arg2);

Just like with any function call, the order of the arguments you pass in maps to the order of the arguments in your function signature.

Here is a slightly fuller example:

(function(first, last) {
    alert("My name is " + last + ", " + first + " " + last + ".");

})("James", "Bond");

If you run this in your browser (or run it in your mind), what gets displayed is My name is Bond, James Bond. And with this, you have learned the basics of how to write an IIFE. This is the easy part. The more interesting (and difficult) part is figuring out the cases when to use an IIFE.

When to Use an IIFE

At this point, the value IIFEs bring to the table seems a little odd. After all, what is so different about an IIFE compared to a function you declare and call immediately like you have always done? The main difference is that an IIFE leaves behind no evidence of its existence after it has run. This is largely because IIFEs are anonymous functions that are nameless. This means you can't track them by examining variables. Because the code you put inside an IIFE is actually inside a function, any variables you declare are local to that function.

Putting all of this together, an IIFE provides you with a very simple way of running code fully inside its own bubble and then disappearing without a trace.

Now that you know what makes IIFEs unique (and extremely confusing), let's look at when you will need to use them.

Avoiding Code Collisions

One of the biggest advantages IIFEs bring is their ability to insulate any code from outside interference. This is important if you are writing code that will be used widely in someone else's application. You want to ensure that any existing (or new) code doesn't accidentally clobber over your variables or override functions and methods. The way to ensure that such accidents don't happen is to wrap all of your code inside an IIFE.

For example, here is a version of the Sweet Content Slider code wrapped into an IIFE:

(function() {
	// just querying the DOM...like a boss!
    var links = document.querySelectorAll(".itemLinks");
    var wrapper = document.querySelector("#wrapper");
    
    // the activeLink provides a pointer to the currently displayed item
    var activeLink = 0;
    
    // setup the event listeners
    for (var i = 0; i < links.length; i++) {
        var link = links[i];
        link.addEventListener('click', setClickedItem, false);
        
        // identify the item for the activeLink
        link.itemID = i;
    }

    // set first item as active
    links[activeLink].classList.add("active");

    function setClickedItem(e) {
        removeActiveLinks();

        var clickedLink = e.target;
        activeLink = clickedLink.itemID;
        
        changePosition(clickedLink);
    }
	
    function removeActiveLinks() {
        for (var i = 0; i < links.length; i++) {
            links[i].classList.remove("active");
        }
    }
    
    // Handle changing the slider position as well as ensure
    // the correct link is highlighted as being active
    function changePosition(link) {
    	var position = link.getAttribute("data-pos");
        wrapper.style.left = position;
        
        link.classList.add("active");
    }
})();

As highlighted in this example, just add the first and last line that wraps everything you are doing into a function that gets immediately executed. You don't have to make any additional modifications. Because all of the code inside the IIFE runs in its own scope and disappears, you don't have to worry about someone else creating their own copies of things found in your code and breaking your functionality.

Closures and Locking In State

There is an important detail about closures that I didn't highlight in the Closures in JavaScript article. That detail is that Closures store their outer values by referencing them. They don't directly store the actual values. Let's take a look at an example to understand what that means.

Let's say we have a function called quotatious:

function quotatious(names) {
    var quotes = [];
    
    for (var i = 0; i < names.length; i++) {   
        
        var theFunction = function() {
            return "My name is " + names[i] + "!";
        }
        
        quotes.push(theFunction);
    }
    return quotes;
}

What this function does should seem pretty simple. It takes an array of names and returns an array of functions that print out the name when called. To use this function, add the following lines of code:

// our list of names
var people = ["Tony Stark", "John Rambo", "James Bond", "Rick James"];

// getting an array of functions
var peopleFunctions = quotatious(people);

// get the first function
var person = peopleFunctions[0];

// execute the first function
alert(person());

When the last line with the alert statement is executed, what would you expect to see? Because our person variable is getting the first item from the array of functions returned by peopleFunctions, it would seem reasonable to expect "My name is Tony Stark!" to appear.

What you actually will see is the following:

something is wrong here, right?

You will see undefined appearing instead of any person's name from the people array...much less the supposedly correct value of Tony Stark. What is going on here?

What is going on is very subtle and highlighted in the following two lines of code:

function quotatious(names) {
    var quotes = [];
    
    for (var i = 0; i < names.length; i++) {   
        
        var theFunction = function() {
            return "My name is " + names[i] + "!";
        }
        
        quotes.push(theFunction);
    }
    return quotes;
}

Your theFunction function relies on the value of names[i]. The value of i is defined by the for loop, and the for loop is outside of the theFunction's scope. What you have is basically a closure with the theFunction function and the variable i being an outer variable:

a closure

Here is where the important detail I mentioned about closures comes into play. The value of i is never locked into the theFunction or the closure. Its value is simply referenced. What you have is something similar to this visualization:

closure reference

Because the value of the i variable is actually referenced, the value of i that your closures reference is increased by one with each iteration of your for loop. That isn't the behavior we want. We want each function in the quotes array to store the value of i that it had when the function was first created. By the time our loop has fully run to completion, the value of i is 4.

Here is a visualization of what is going on:

ah, now I see what is going on

Because i is 4 and greater than the number of items in the names array input, you get undefined when the following line executes with names[4]:

function quotatious(names) {
    var quotes = [];
    
    for (var i = 0; i < names.length; i++) {   
        
        var theFunction = function() {
            return "My name is " + names[i] + "!";
        }
        
        quotes.push(theFunction);
    }
    return quotes;
}

At this point, we understand what the code does and why it doesn't work as it is currently written. The solution is to lock in the value of our outer variable, the troublesome i, inside the closure. This will involve, as you might have guessed, the assistance of an IIFE.

Below is the modified version of the quotatious function that does what we want it to do:

function quotatious(names) {
    var quotes = [];
    
    for (var i = 0; i < names.length; i++) {   
        (function(index) {
            var theFunction = function() {
                return "My name is " + names[index] + "!";
            }
            quotes.push(theFunction);
        })(i);
    }
    return quotes;
}

Notice that the i variable is passed in as an argument to our IIFE. This argument, now referenced inside the IIFE by the index variable, is local to whatever the function does. The state of what used to be an outer variable is now locked in! This change ensures that the function inside the quotes array has its own copy of the array index it needs so that the right person is being referenced. You no longer have references to outer variables that change and cause your code to break. W00t!

Sometimes referencing outer variables is what you want!

 I am most certainly not saying to always use an IIFE when an outer variable changes after a closure has been created. There may be times where you want your closure to work with the updated value of an outer variable, so in those cases, don't use an IIFE to lock-in the value.

 

Making Things Private

In JavaScript, you don’t have an easy, built-in way to limit the visibility of variables and properties you end up creating. This means it is difficult to have parts of your app hidden from other parts of your app.

Take a look at the following example that highlights this problem:

var weakSauce = {
    secretCode: "Zorb!",

    checkCode: function (code) {
        if (this.secretCode == code) {
            alert("You are awesome!");   
        } else {
            alert("Try again!");   
        }
    }
};

You have an object called weakSauce that has two properties called secretCode and checkCode. This is a very naive password checker. When you pass in a code value to the checkCode function, it will check if what you entered matches the value of secretCode. If it matches, you are awesome will get displayed. If it isn’t, you are still awesome…despite what this code will tell you.

Now, here is where some privacy in your code may help. Nothing prevents me, you, or someone who uses this code from checking the value of secretCode directly:

var bar = Object.create(weakSauce);
alert(bar.secretCode) // sigh :(

This is probably not what you intended when creating the secretCode property. The reason isn't because secretCode is named with the word secret in it. It is part of an implementation detail that you may want to change at any time. The checkCode function is what you would intend people to use. Any other variable or property is fair game for you to change whenever you want. If other pieces of code take a dependency on implementation details, their code may break whenever you make a change. That's why keeping some items private is important. That is why the secretCode property should be hidden to everything except the internals of the weakSauce object. In other languages, you could add an access modifier like private to secretCode, and that would be the end of this entire conversation. JavaScript isn't like other languages. You have to jump through hoops to solve your problem, and one such awesome hoop to is our friendly IIFE.

By taking advantage of the local scope IIFE’s create, you can selectively choose what to expose or what not to expose. Here is a version of the same example that works as we would like:

var awesomeSauce = (function () {
    var secretCode = "Zorb!";

    function privateCheckCode(code) {
        if (secretCode == code) {
            alert("You are awesome!");   
        } else {
            alert("Try again!");   
        }
    }

    // the public method we want to return
    return {
        checkCode: privateCheckCode
    };
})();

Let's repeat what we tried earlier with this new awesomeSauce function:

var foo = Object.create(awesomeSauce);
alert(foo.secretCode); // undefined

This time around, you won't be able to access secretCode. The reason is that the contents of secretCode are buried inside the IIFE and not accessible publicly. In fact, the only thing that is publicly exposed is what you have here:

var awesomeSauce = (function () {
    var secretCode = "Zorb!";

    function privateCheckCode(code) {
        if (secretCode == code) {
            alert("You are awesome!");   
        } else {
            alert("Try again!");   
        }
    }

    // the public method we want to return
    return {
        checkCode: privateCheckCode
    };
})();

By only returning the checkCode property that internally references the privateCheckCode function (which is a closure), you get all the functionality you originally had while only exposing checkCode as the property in awesomeSauce that other parts of your app can safely access.

There a more formal name for what I've just shown you here. It's known as the Revealing Module Pattern, and there is a ton of good stuff on the net about it. My favorite is the following concise take of this pattern by Addy Osmani.

Remember, your JavaScript code is an open book!

While you may have just learned about a way to keep the internals of your code private, it is only private to the typical code you write. Unlike other languages, JavaScript's source is always fully accessible. Even with obfuscation and other techniques, if your browser can see your code, then anybody else with a few extra seconds to spare can as well.

For example, using the Chrome Developer Tools, I can easily inspect the closure stored by checkCode and clearly see the value of the secretCode variable:

the closure is not private after all :(

Essentially, what I'm trying to say is this - don't rely on client-side JavaScript for dealing with things you truly want to keep private. Instead, do what everyone else does and use some server-side service that provides you with a private environment where top secret things get done. The server then only returns the things you want exposed publicly back to JavaScript.

Conclusion

An IIFE (short for Immediately Invoked Function Expression) is one of those bizarre things in JavaScript that turns out to play a very useful role once you give it a chance. The main reason you will need to learn about IIFEs is because JavaScript lacks privacy. This problem becomes more annoying when you are working on increasingly larger and more complex JavaScript apps (who usually have increasingly larger and more complex closures), so the local scope created by an IIFE is the ultimate blunt instrument for solving all of your problems. As with all blunt instruments, do be careful when using them.

Just a final word before we wrap up. If you have a question and/or want to be part of a friendly, collaborative community of over 220k other developers like yourself, post on the forums for a quick response!

Kirupa's signature!

The KIRUPA Newsletter

Thought provoking content that lives at the intersection of design 🎨, development 🤖, and business 💰 - delivered weekly to over a bazillion subscribers!

SUBSCRIBE NOW

Creating engaging and entertaining content for designers and developers since 1998.

Follow:

Popular

Loose Ends

:: Copyright KIRUPA 2024 //--