Blog

Front End Development topics with a touch of humor

Introduction to Closures

Learn this exotic-sounding feature so you can pass the technical interview!

October 11, 2020


Why learn closures? What is a closure? Is it just me, or is closure the kind of word that when you look at it enough times, you become convinced it's misspelled, but you then you check and realize it's not, and then you start to wonder if your organic hard drive is starting to get fragmented, and--

Okay, maybe it's just me.

As to the why, the subtitle alluded to one reason. Asking about closures is, I hear, a common thing in technical interviews. That's a good enough reason in itself, but, as JavaScript, the Definite Guide, by David Flanagan says, "there are a number of powerful programming techniques that that involve this kind of nested function closures." And we all want powerfur programming techniques, right?

Let's dive in.

The definition of closure

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. MDN

I don't know about you, but the first time I read that, I wasn't 100% sure it was English. What the is this bundling stuff, and what are these lexical references-environment-what? Let's break it down.

We know what a function is. What are these references to its surrounding state?

Functions, it's important to note, can have different results depending on their surrounding state. This is called their (two-dollar word alert): lexical environment. The big concept here is that functions execute based on the environment in which they were defined, not where they are executed.

So the function must "remember" where it was defined. This memory is the reference whereof I spoke; this is the thing that was "bundled" in the function. Think of it with an analogy. All functions are made in various factories, but those functions are then shipped out all over the world. But if you open up the function, you get the "Made in the Republic of Liechtenstein" in it, right?

That little tag is the reference. The Republic of Liechtenstein is the lexical scope. No matter where our little function goes, it will always remember where it was made.

Consider this example.

        const ref = "The wide world";
        function returnRef() {
            const ref = "The Republic of Liechtenstein";
            function action() {
                return ref;
            }
        return action();
        }
        returnRef();
        //"The Republic of Liechtenstein"
        

It's worth a bit of analysis. We have a function that returns a function and two variables with the same name. The variable is defined in the global scope and then again in the local scope of returnRef. In returnRef, the function action is declared and then returned (while executing).

The inner function uses the value from the local scope, as it is both defined and executed in this local scope. Now let's change it up. We'll define it inside a function, just as before, but we will execute it in the global scope.

            const ref = "The wide world";
            function returnRef() {
                const ref = "The Republic of Liechtenstein";
                function action() {
                    return ref;
                }
            return action;
            }
        

The only thing changed is that instead of returning action(), we're returning action--that is, we're returning the function instead of the function's return value.

        const myFunc = returnRef();
        myFunc();
        //"The Republic of Liechtenstein"
        

Same result, but why is this cool?

Well, when we assign returnRef() to myFunc, the return value the function "action." Then when we invoke myFunc, we are invoking "action." But notice we are doing that in the global namespace. Even so, the function remembers its local namespace, and thus uses the local variable value.

I'll get into why this is cool and how you can use this feature in later posts.