Andy from Webcrunch

Subscribe for email updates:

How to REALLY Learn JavaScript Series: Part 8 Understanding Closures
Portrait of Andy Leverenz
Andy Leverenz

June 9, 2015

Last updated November 5, 2023

How to REALLY Learn JavaScript Series: Part 8 Understanding Closures

Some developers attest to their knowledge of JavaScript by being able to correctly explain what a closure is in JavaScript and why it is useful. Bragging rights aside closures are often made more complex than they need to be. To understand closures effectively, you first need to understand different types of scope in the language.

Scope

There are two types of scope in JavaScript. Global and Local. The global scope can best be described as having access to anything throughout your JavaScript code or application while the local scope is scope within a function that doesn’t always have access to outside variables or functions. To make a better sense of this check out some quick examples below.

Global Scope

var myGlobalVariable = "global";

// Global scope. Here I have access to the variable created at a global level.
function fn() {
    alert(myGlobalVariable);
}

Local Scope

var myLocalVariable = "local";

// pass it as a parameter
function fn(myLocalVariable) {
 alert(myLocalVariable);
}

// or define/reassign it within a function
function newfunc() {
  var myLocalVariable = "local";
  alert(myLocalvariable);
}

Understanding Closures

Closures are a way to let a function have persistent, private variables - that is, variables that only one function knows about, where it can keep track of info from previous times that it was run. For some reason when reading about closures you get confused really fast. Academic examples just leave you guessing and throw you for a loop! (no pun intended, seriously). The best way I found out how to understand them is through realistic code examples so I will carry that torch forward to anyone who may have an interest.

Closure

function outerFunction(){
   var x = 1;
   function innerFunction(){
     alert(x);
     x++;
   }
   return innerFunction;
}

var counterFunction = outerFunction();
counterFunction(); // 1
counterFunction(); // 2

You may be asking yourself what the hell you just looked at. Don't worry. It confused me too. Let's go line by line to give a little explanation at this madness.

At first glance, you will see a variable at the bottom called counterFunction that looks we bit out of place. This variable is being assigned to our outerFunction() or at least that's what it looks like. In reality it is being assigned to the innerFunction() since the outerFunction() is responsible for returning it's contents, which again is the innerFunction(). Still with me? So far we have counterFunction = innerFunction.

The innerFunction() alerts our variable which is defined inside our outerFunction and then gets returned. You may think at this point we no longer have a use for the innerFunction and you are right but since we have assigned it to a variable, counterFunction, we still need it. We also need access to the variable x inside our outerFunction function.

In this odd outcome, we now have access to both private and persistent variables. Think of it as a place for the counterFunction to keep records, safe from any garage collection.

Why use this?

A closure could be a good solution for any type of function that may require private information. Anything from user ids, passwords, or unique identifiers could all make great use cases. While it's hard to wrap your head around the power that exists makes it really amazing to use. If you need a variable to stick around during the life of your application, for example, is another good use case to put in place.

More Examples for Clarity

If none of that made sense (it may take a couple of read-throughs), Let me try to follow-up with a few more examples to hopefully convey a practical example of a closure.

Below I keep some variables handy for callbacks. The reference to the variables is always present even after calling the function. The console outputs a number every 1000 milliseconds until it reaches the last one in our array.

    var myNumbs = [1, 2, 3, 4, 5, 6];
       for (var i=0; i < myNumbs.length; i++) {
      (function(a){
          setTimeout(function(){
             console.log(myNumbs[a]);
          }, 1000*a);
      })(i);
   }

Below I make use of private variables that only exist inside the closure. You can't call the private function directly thus explaining its power. The public function is of course...public.

pFunc = (function () {
    var privatefunction = function () {
        alert('hello');
    }

    return {
        publicfunction : function () {
            privatefunction();
        }
    }
})();

And here's another very basic approach, similar to the syntax and code above.

function groceryTrips(x) {
  var list = 10

  function items(y) {
    alert(x + y + (++list)); // alerts 23
  } 

 items(10);
}
groceryTrips(2);

This code will always alert 23 because items can access the x argument of the groceryTrips function. It can also access the list variable from groceryTrips as well. Accessing variables outside of the immediate scope of your function are what creates a closure.

Finishing Up

Closures are confusing, no doubt. Hopefully, my examples and explanations spread some light on the subject. If you need more examples I strongly recommend checking out the Stack Overflow community website to get some help or just see what others have come up with in terms of remembering what closures are and how they can be of use.

The Series So Far

Link this article
Est. reading time: 5 minutes
Stats: 388 views

Categories

Collection

Part of the Beginner JavaScript collection