JavaScript
Article

Demystifying JavaScript Closures, Callbacks and IIFEs

By Ivaylo Gerchev

We’ve already taken a close look at variable scope and hoisting, so today we’ll finish our exploration by examining three of the most important and heavily-used concepts in modern JavaScript development — closures, callbacks and IIFEs.

Closures

In JavaScript, a closure is any function that keeps reference to variables from its parent’s scope even after the parent has returned.

This means practically any function can be considered a closure, because, as we learned in the variable scope section from the first part of this tutorial, a function can refer to, or have access to –

  • any variables and parameters in its own function scope
  • any variables and parameters of outer (parent) functions
  • any variables from the global scope.

So, chances are you’ve already used closures without even knowing it. But our aim is not just to use them – it is to understand them. If we don’t understand how they work, we can’t use them properly. For that reason, we are going to split the above closure definition into three easy-to-comprehend points.

Point 1: You can refer to variables defined outside of the current function.

function setLocation(city) {
  var country = "France"; 

  function printLocation() {       
    console.log("You are in " + city + ", " + country);  
  }

  printLocation();
}

setLocation ("Paris");  // output: You are in Paris, France

Try out the example in JS Bin

In this code example, the printLocation() function refers to the country variable and the city parameter of the enclosing (parent) setLocation() function. And the result is that, when setLocation() is called, printLocation() successfully uses the variables and parameters of the former to output “You are in Paris, France”.

Point 2: Inner functions can refer to variables defined in outer functions even after the latter have returned.

function setLocation(city) {
  var country = "France"; 

  function printLocation() {       
    console.log("You are in " + city + ", " + country);  
  }

  return printLocation;
}

var currentLocation = setLocation ("Paris");   

currentLocation();   // output: You are in Paris, France

Try out the example in JS Bin

This is almost identical to the first example, except that this time printLocation() is returned inside the outer setLocation() function, instead of being immediately called. So, the value of currentLocation is the inner printLocation() function.

If we alert currentLocation like this – alert(currentLocation); – we’ll get the following output:

function printLocation () {       
  console.log("You are in " + city + ", " + country);  
}

As we can see, printLocation() is executed outside its lexical scope. It seems that setLocation() is gone, but printLocation() still has access to, and “remembers”, its variable (country) and parameter (city).

A closure (inner function) is able to remember its surrounding scope (outer functions) even when it’s executed outside its lexical scope. Therefore, you can call it at any time later in your program.

Point 3: Inner functions store their outer function’s variables by reference, not by value.

function cityLocation() {
  var city = "Paris";

  return {
    get: function() { console.log(city); },  
    set: function(newCity) { city = newCity; }
  };
}

var myLocation = cityLocation();

myLocation.get();           // output: Paris
myLocation.set('Sydney');
myLocation.get();           // output: Sydney

Try out the example in JS Bin

Here cityLocation() returns an object containing two closures – get() and set() – and they both refer to the outer variable city. get() obtains the current value of city, while set() updates it. When myLocation.get() is called for the second time, it outputs the updated (current) value of city – “Sydney” – rather than the default “Paris”.

So, closures can both read and update their stored variables, and the updates are visible to any closures that have access to them. This means that closures store references to their outer variables, rather than copying their values. This is a very important point to remember, because not knowing it can lead to some hard-to-spot logic errors – as we’ll see in the “Immediately-Invoked Function Expressions (IIFEs)” section.

One interesting feature of closures is that the variables in a closure are automatically hidden. Closures store data in their enclosed variables without providing direct access to them. The only way to alter those variables is by providing access to them indirectly. For example, in the last piece of code we saw that we can modify the variable city only obliquely by using the get() and set() closures.

We can take advantage of this behavior to store private data in an object. Instead of storing the data as an object’s properties, we can store it as variables in the constructor, and then use closures as methods that refer to those variables.

As you can see, there is nothing mystical or esoteric around the closures – only three simple points to remember.

Callbacks

In JavaScript, functions are first-class objects. One of the consequences of this fact is that functions can be passed as arguments to other functions and can also be returned by other
functions.

A function that takes other functions as arguments or returns functions as its result is called a higher-order function, and the function that is passed as an argument is called a callback function. It’s named “callback” because at some point in time it is “called back” by the higher-order function.

Callbacks have many everyday usages. One of them is when we use the setTimeout() and setInterval() methods of the browser’s window object – methods that accept and execute callbacks:

function showMessage(message){
  setTimeout(function(){
    alert(message);
  }, 3000);  
}

showMessage('Function called 3 seconds ago');

Try out the example in JS Bin

Another example is when we attach an event listener to an element on a page. By doing that we’re actually providing a pointer to a callback function that will be called when the event occurs.

// HTML

<button id='btn'>Click me</button>

// JavaScript

function showMessage(){
  alert('Woohoo!');
}

var el = document.getElementById("btn");
el.addEventListener("click", showMessage);

Try out the example in JS Bin

The easiest way to understand how higher-order functions and callbacks work is to create your own. So, let’s create one now:

function fullName(firstName, lastName, callback){
  console.log("My name is " + firstName + " " + lastName);
  callback(lastName);
}

var greeting = function(ln){
  console.log('Welcome Mr. ' + ln);
};

fullName("Jackie", "Chan", greeting);

Try out the example in JS Bin

Here we create a function fullName() that takes three arguments – two for the first and last name, and one for the callback function. Then, after the console.log() statement, we put a function call that will trigger the actual callback function – the greeting() function defined below the fullName(). And finally, we call fullName(), where greeting() is passed as a variable – without parentheses – because we don’t want it executed right away, but simply want to point to it for later use by fullName().

We are passing the function definition, not the function call. This prevents the callback from being executed immediately, which is not the idea behind the callbacks. Passed as function definitions, they can be executed at any time and at any point in the containing function. Also, because callbacks behave as if they are actually placed inside that function, they are in practice closures: they can access the containing function’s variables and parameters, and even the variables from the global scope.

The callback can be an existing function as shown in the preceding example, or it can be an anonymous function, which we create when we call the higher-order function, as shown in the following example:

function fullName(firstName, lastName, callback){
  console.log("My name is " + firstName + " " + lastName);
  callback(lastName);
}

fullName("Jackie", "Chan", function(ln){console.log('Welcome Mr. ' + ln);});

Try out the example in JS Bin

Callbacks are heavily used in JavaScript libraries to provide generalization and reusability. They allow the library methods to be easily customized and/or extended. Also, the code is easier to maintain, and much more concise and readable. Every time you need to transform your unnecessary repeated code pattern into more abstract/generic function, callbacks come to the rescue.

Let’s say we need two functions – one that prints information about published articles and another that prints information about sent messages. We create them, but we notice that some part of our logic is repeated in both of the functions. We know that having one and the same piece of code in different places is unnecessary and hard to maintain. So, what is the solution? Let’s illustrate it in the next example:

function publish(item, author, callback){   // Generic function with common data
  console.log(item);
  var date = new Date();

  callback(author, date);
}

function messages(author, time){   // Callback function with specific data
  var sendTime = time.toLocaleTimeString();
  console.log("Sent from " + author + " at " + sendTime);
}

function articles(author, date){   // Callback function with specific data
  var pubDate = date.toDateString();
  console.log("Written by " + author);
  console.log("Published " + pubDate);
}

publish("How are you?", "Monique", messages);

publish("10 Tips for JavaScript Developers", "Jane Doe", articles);

Try out the example in JS Bin

What we’ve done here is to put the repeated code pattern (console.log(item) and var date = new Date()) into a separate, generic function (publish()), and leave only the specific data inside other functions – which are now callbacks. That way, with one and the same function we can print information for all sorts of related things – messages, articles, books, magazines and so on. The only thing you need to do is to create a specialized callback function for each type, and pass it as an argument to the publish() function.

Immediately-Invoked Function Expressions (IIFEs)

An Immediately-invoked function expression, or IIFE (pronounced “iffy”), is a function expression (named or anonymous) that is executed right away after its creation.

There are two slightly different syntax variations of this pattern:

// variant 1

(function () {
  alert('Woohoo!');
})();

// variant 2

(function () {
  alert('Woohoo!');
}());

To turn a regular function into an IIFE you need to perform two steps:

  1. You need to wrap the whole function in parentheses. As the name suggests, an IIFE must be a function expression, not a function definition. So, the purpose of the enclosing parentheses is to transform a function definition into an expression. This is because, in JavaScript, everything in parentheses is treated as an expression.
  2. You need to add a pair of parentheses at the very end (variant 1), or right after the closing curly brace (variant 2), which causes the function to be executed immediately.

There are also three more things to bear in mind:

First, if you assign the function to a variable, you don’t need to enclose the whole function in parentheses, because it is already an expression:

var sayWoohoo = function () {
  alert('Woohoo!');
}();

Second, a semicolon is required at the end of an IIFE, as otherwise your code may not work properly.

And third, you can pass arguments to an IIFE (it’s a function, after all), as the following example demonstrates:

(function (name, profession) {
  console.log("My name is " + name + ". I'm an " + profession + ".");
})("Jackie Chan", "actor");   // output: My name is Jackie Chan. I'm an actor.

Try out the example in JS Bin

It’s a common pattern to pass the global object as an argument to the IIFE so that it’s accessible inside of the function without having to use the window object, which makes the code independent of the browser environment. The following code creates a variable global that will refer to the global object no matter what platform you are working on:

(function (global) {
  // access the global object via 'global'
})(this);
</code></pre>

<p>This code will work both in the browser (where the global object is <code>window</code>), or in a Node.js environment (where we refer to the global object with the special variable <code>global</code>). </p>

<p>One of the great benefits of an IIFE is that, when using it, you don’t have to worry about polluting the global space with temporary variables. All the variables you define inside an IIFE will be local. Let’s check this out:</p>

[code language="javascript"](function(){

  var today = new Date();
  var currentTime = today.toLocaleTimeString();
  console.log(currentTime);   // output: the current local time (e.g. 7:08:52 PM)

})();

console.log(currentTime);   // output: undefined

Try out the example in JS Bin

In this example, the first console.log() statement works fine, but the second fails, because the variables today and currentTime are made local thanks to the IIFE.

We know already that closures keep references to outer variables, and thus, they return the most recent/updated values. So, what do you think is going to be the output of the following example?

function printFruits(fruits){
  for (var i = 0; i &lt; fruits.length; i++) {
    setTimeout( function(){
      console.log( fruits[i] );
    }, i * 1000 );
  }
}

printFruits(["Lemon", "Orange", "Mango", "Banana"]);

Try out the example in JS Bin

You may have expected that the names of the fruits would be printed one after another at one-second intervals. But, in practice, the output is four times “undefined”. So, where is the catch?

The catch is that the value of i, inside the console.log() statement, is equal to 4 for each iteration of the loop. And, since we have nothing at index 4 in our fruits array, the output is “undefined”. (Remember that, in JavaScript, an array’s index starts at 0.) The loop terminates when i < fruits.length returns false. So, at the end of the loop the value of i is 4. That most recent version of the variable is used in all the functions produced by the loop. All this happens because closures are linked to the variables themselves, not to their values.

To fix the problem, we need to provide a new scope – for each function created by the loop – that will capture the current state of the i variable. We do that by closing the setTimeout() method in an IIFE, and defining a private variable to hold the current copy of i.

function printFruits(fruits){
  for (var i = 0; i &lt; fruits.length; i++) {
    (function(){
      var current = i;                    // define new variable that will hold the current value of "i"
      setTimeout( function(){
        console.log( fruits[current] );   // this time the value of "current" will be different for each iteration
      }, current * 1000 );
    })();
  }
}

printFruits(["Lemon", "Orange", "Mango", "Banana"]);

Try out the example in JS Bin

We can also use the following variant, which does the same job:

function printFruits(fruits){
  for (var i = 0; i &lt; fruits.length; i++) {
    (function(current){
      setTimeout( function(){
        console.log( fruits[current] );
      }, current * 1000 );
    })( i );
  }
}

printFruits(["Lemon", "Orange", "Mango", "Banana"]);

Try out the example in JS Bin

An IIFE is often used to create scope to encapsulate modules. Within the module there is a private scope that is self-contained and safe from unwanted or accidental modification. This technique, called the module pattern, is a powerful example of using closures to manage scope, and it’s heavily used in many of the modern JavaScript libraries (jQuery and Underscore, for example).

Conclusion

The aim of this tutorial has been to present these fundamental concepts as clearly and concisely as possible – as a set of simple principles or rules. Understanding them well is key to being a successful and productive JavaScript developer.

For a more detailed and in-depth explanation of the topics presented here, I recommend you take a look at Kyle Simpson’s You Don’t Know JS: Scope & Closures.

Free Guide:

7 Habits of Successful CTOs

"What makes a great CTO?" Engineering skills? Business savvy? An innate tendency to channel a mythical creature (ahem, unicorn)? All of the above? Discover the top traits of the most successful CTOs in this free guide.

Comments
felgall

That statement makes no sense any you appear to have a completely wrong idea about closures - since none of your supposed closure examples actually use a closure.

A closure occurs when a variable or function defined inide of the inner function's scope continues to be accessible to the outer function even after the inner function has returned. Just about the exact opposite of what you said.

See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures where tyour examples match the first example that illustrates lexical scope (not closures) The next example on that page illustrates the creation of a closure by returning the function from the inn er scope without executing it and then executing it later after the scope it was created in has closed. There are further example further down that page.

To create a closure you must return something that references elements with inner scope.

Jeff_Mott

Felgall, the MDN example you're referencing is virtually identical to the article's "Point 2" example.


felgall

Okay - I was misled by the completely incorrect description of what a closure actually is and missed that after the first supposed closure example that didn't include a closure that the subsequent examples started to use one. A very confusing article about closures.

There are basically three ways to create a closure

example1 = function(x) {
var myvar1 = x;
return function() {return myvar1;};
}

var aa;
example2 = function(y) {
var myvar2 = y;
aa = function() {return myvar2;};
}

example3 = function(z) {
var bb, myvar3;
bb = function() {return myvar3;};
myvar3 = z;
return bb;
}
Jeff_Mott

Actually the article got it right. A closure is an inner function that has access to an outer function's variables. And in fact the MDN article you referenced says the same.

felgall

Inner functions always have access to outer functions variables - a closure is only created if those variables remain accessible after the outer function has closed.

Jeff_Mott

Let's be clear about something first. This isn't the same argument you made above.

The outer function never has access to the inner function's variables. Rather, the inner function has access to the outer function's variables. The article didn't get it backwards, you did.

And finally, I would agree that a closure only seems useful if we use the inner function sometime after the outer has finished, but if we're going to get technical, then the closure is actually created at the moment that we create the inner function.

felgall

I agree with that.

My two arguments appear to contradict one another because I was inconsistent in my use of inner and outer. There are actually three levels of functions involved in creating a closure and in my first argument I was using inner to refer to the innermost of the three and outer the middle one. In the second argument I was using inner for the middle one and outer for the outermost.

pinoniq

A closure is not any function. This is just plain wrong. Closure have nothing to do with a function, in theory.

A function in JavaScript is an Object that inherits the function.prototype methods and arguments (apply(), call(), ...)

A closure on the other hand, refers to the execution context of a callable. And here lies the small difference in meaning where a lot of geeks (like me) tend to get 'mad' about. Ofcourse, execution context kind of only makes sense when executing a function. And yes, it says something about 'what do I have acces to'. But understanding the difference makes understanding the 'this' word so much easier. And the methods like .call() and apply() suddenly start to make real sense.

daz4126

To understand closures you need to understand the scope of a function, which is what the first example is for (it's not an example of a closure).

A closure is a reference to a value created inside the scope of a function but is still available after that function has executed.

Here's a simple example from the Novice to Ninja book:

function closure(){
var inside = "I was created inside the function";
return inside;
}

The value of the inside variable is unavailable outside the closure() function:

inside;
<< Error: "inside is not defined"

But we can create a closure by invoking the closure() function, which will return the value of inside and make it available outside the function:

outside = closure();
<< "I was created inside the function"

More often than not though a closure will be a function that is returned and keeps the reference to variables created in the original function's scope.

Jeff_Mott

Unfortunately that isn't really an example of a closure. That's just a plain old return value.

Paul_Wilkins

Yes indeed - the variable being updated has to be situated outside of the function to be considered a closure.

The important aspect of a closure is that an outer function returns an inner function, with that returned inner function retaining knowledge of variables from the outer one.

The Jibbering Closures FAQ I still find to be highly insightful in regard to closures.

function exampleClosureForm(arg1, arg2){
    var localVar = 8;
    function exampleReturned(innerArg){
        return ((arg1 + arg2)/(innerArg + localVar));
    }
    /* return a reference to the inner function defined as -
       exampleReturned -:-
    */
    return exampleReturned;
}

var globalVar = exampleClosureForm(2, 4);
daz4126

But the point is that the returned value was created inside the lexical scope of another function and would normally be inaccessible outside of that function.

I admit that the example is basic and in most cases a function would be returned to form a closure, but I don't think that's necessary for it to actually be a closure.

All this discussion certainly shows that they are a difficult concept to define!

Jeff_Mott

There's a difference between values and variables. Values don't have scope; variables do. Getting a value outside of a function isn't anything special. But accessing a variable after the point where it normally would have been destroyed is a trick made possible by closures.

Paul_Wilkins

As a followup, this is only possible to achieve thanks to the return being a function, as it retains the environment scope in which it was created.

daz4126

Yes, okay, I concede that in order to have control over the variable that was created then you will need to return it in a function. I still think that the first example in the article and the example I gave are important in building up to demonstrating closures as they demonstrate the scope of a function and the fact that by using the return statement you can access variables created inside another function.

Paul_Wilkins

Sorry Daz, but your example is not helpful in regard to closures. The following diagram might help to clarify things.

It's from another useful blog post on Closures

Jeff_Mott

This part sounds fine. Yes, the first example in the article and the example you gave are a fine demonstration of scope.

But this isn't quite right. In this discussion, remember it's important to distinguish values and variables. A return statement passes a value. You're not creating a closure just by returning some value.

daz4126

Yes I agree with you on this - it's important that if you just return a variable then it's the value of the variable that is returned and not the variable itself, which is what happens if it is returned inside a function. My example wasn't a great example, sorry if it confused anybody.

DAZ

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in JavaScript, once a week, for free.