Jorge Valle

Jorge Valle

Jorge Valle is a front end developer with a particular passion for, and expertise in, JavaScript and user interfaces. Lately, he's also been diving into machine learning.

3 examples of JavaScript closures

Closures in JavaScript are a really cool mechanism that helps us wrap up data with functions that act on that data. This data is usually a representation of state, at least in the world of web development. While they might seem mysterious to some programmers, these three simple examples should help shine some light on them.

While I've never been explicitly asked about closures during a coding interview, many engineers cite them as a common interview question. Furthermore, many would argue that the entire power of JavaScript as a language isn't open to you until you have a firm grasp on closures, so it's best to understand closures thoroughly.

JavaScript features first-class functions: functions can be returned from other functions, or passed in as arguments to other functions. Whenever you have a function that is returning another function, or is taking a function as an argument, watch out for closures being created.

That's because closures are formed when a function is transported - and executed - outside of its lexical scope, while still keeping references to values within its lexical scope.

Closures are formed when a function is transported - and executed - outside of its lexical scope, while still keeping references to values within its lexical scope.

This statement is probably best illustrated with an example.

Example 1: String logger

In this example, we have two functions: outer(), and inner().

inner() is returned from inside outer. Due to the rules of lexical scoping, the inner() function has access to the let i variable declared in the scope of outer(). I think most programmers are comfortable with that concept. The interesting part is that we then assign outer() to another variable runOuter, effectively transporting it's inner workings outside of its lexical scope.

This execution of the function in a different lexical scope is what creates the closure. We will follow the same pattern in the examples below.

Example 2: Log plus one

Continuing on very much the same idea as above, we create a function that logs a number in the outer function, but that number gets increased by one in the inner function. Also notice that, for illustration, the inner function in this case is anonymous; we don't need to refer to it by name anywhere for the code to work.

We can run runLogger() anytime, and we can be sure it'll hold a reference to the currently iterated i. Cool!

Example 3: Array cycler

We're continuing with the same approach as above. Here's a function that uses a closure to keep track of state, in order to cycle over an array. The important concept here is that the state - in this case the current index at which the array is at - is packed into the names() function. When cycleNames() is called, the closure is referencing the i variable that gets updated.

Let's take a step back.

All of these examples have a common thread running through them: a variable local to the outer function is being changed from the inner function. Then the outer function runs the inner function, so the inner function keeps a reference to its lexical scope regardless of where it's run. It can be executed anywhere that it can be transported to, and it will still keep that reference. That's what makes closures such a powerful construct.

Furthermore, this packing of data along with the functions that act on it can go a long way towards minimizing side-causes and side-effects.

Pretty cool stuff.

Bonus example: Nonce function

A bonus fourth example.

This nonce function executes only once, without having to reference a state variable declared outside of it's scope. It's the fact that it can execute only once without referencing a non-local variable that makes it portable, and more in line with functional programming, as it causes no side-effects.

Finally, if you are ever doubtful whether you are dealing with closures, a simple way to confirm their existence is through the Chrome Dev Tools. If you place a breakpoint in your code, you can inspect the scope manager at that point in time. The tool wil allow you to see which values are being closed over.


Books, patrons and coffee in Caffè San Marco, Trieste