Sign in
Log inSign up

Understanding Closures and How it is used in JavaScript

Jude Miracle's photo
Jude Miracle
·Jul 29, 2021·

6 min read

tim-gouw-1K9T5YiZ2WU-unsplash.jpg

Closures in JavaScript are one of those concepts that many find difficult to understand. This article will explain the meaning of closure, and how it is used in JavaScript with examples.

What is closure?

A closure is a function having access to the parent scope, even after the parent function has closed. In other words, A closure gives you access to an outer function’s scope from an inner function. In JavaScript, Closure means that an inner function always has access to the variables and parameters of its outer function, even after the outer function has returned.

The closure is created when an inner function has access to its outer function variables and arguments. The inner function has access to –

  • Its own variables.
  • Outer function's variables and arguments.
  • Global variables.

Before going into a deeper understanding of closures, you will need to understand lexical scoping first. If you already know about it, skip the next part.

Lexical Scoping

Lexical Scoping defines how variable names are resolved in nested functions: inner functions contain the scope of parent functions even if the parent function has returned.

Lexical scope is the key to making closures work. Here's a quote from Wikipedia about closures and lexical scope:

In computer science, a closure is a first-class function with free variables that are bound in the lexical environment. Such a function is said to be "closed over" its free variables. A closure is defined within the scope of its free variables, and the extent of those variables is at least as long as the lifetime of the closure itself.

    var scope = "global scope";
     function whatIsAscope(){
         var scope = "local scope";
         function fun() {
                 return scope;
          }
      return fun;
}
whatIsAscope();

The above code will return "local scope". It will not return "global scope". Because the function fun() counts where it was originally defined which is under the scope of function whatIsAscope().

It will not bother from whatever it is being called the global scope or from within another function, that's why the global scope value "global scope" will not be printed.

This is called lexical scoping where "functions are executed using the scope chain that was in effect when they were defined" - according to JavaScript Definition Guide.

Lexical scope is very important in JavaScript.

Another Example

     var name = "outer";
         function one() {
    var name = "middle";
    var other = "findme";
        function two() {
    var name = "inner";
    // Here `name` is "inner" and `other` is "findme"
    console.dir({name: name, other: other});
  }
  two();
  // Here `name` is "middle" and `other` is "findme"
  console.dir({name: name, other: other});
}
one();
// Here `name` is "outer" and `other` is undefined.
console.dir({name: name});
console.dir({other: other});

We can see that local variables in an inner scope can shadow variables by the same name in the outer scope. But from the outside, variables the inside don't exist. Lexical scope is based on the location of the variables in the nesting in the code. It doesn't care about how you might take to get to the inner function. That's how closures can make inner variables usable.

Now you know about Lexical scoping, let’s get into the track and get back to Examples of Closures in action.

Examples of Closures in action

Every function in JavaScript maintains a link to its outer lexical environment. A lexical environment is a map of all the names (eg. variables, parameters) within scope, with their values.

So, whenever you see the function keyword, the code inside that function has access to variables declared outside the function.

     function foo(x) {
  var temp = 3;

  function bar(y) {
    console.log(x + y + (++temp)); // will log 16
  }

  bar(10);
}

foo(2);

Here we have two functions:

  • an outer function foo which has a variable temp, and returns the inner function.

  • an inner function bar accesses the outer variable temp, within its function body. The code snippet above means that x =2 and y =10. This will log 16 because function bar closes over the parameter x and the variable temp, both of which exist in the lexical environment of outer function foo.

Function bar, together with its link with the lexical environment of function foo is a closure.

A function doesn't have to return to create a closure. Simply under its declaration, every function closes over its enclosing lexical environment, forming a closure.

function foo(x) {
  var temp = 3;

  return function (y) {
    console.log(x + y + (++tmp)); // will also log 16
  }
}

var bar = foo(2);
bar(10); // 16
bar(10); // 17

The above function will also log 16 because the code inside bar can still refer to argument x and variable temp, even though they are no longer directly in scope.

However, since temp is still hanging around inside the bar's closure, it is available to be increased. It will be increased each time you call bar.

Another example

Let's try it with the new ES6 syntax.

 const outer = () => {
     const greeting = 'Good morning';
     const inner = () => {
          alert(greeting);
       }
      return outer;
} 
const newFunc = outer();
newFunc();

if we load up this program on our website. the JavaScript engine will see and ok, we see a variable outer that's a function. Then in a new line, we want to assign the variable newFunc and want it to get the result of outer. So the program runs outer and sees that we want to create a variable greeting which value is "Good morning". We also see that we want to create another function inner and we are returning that function. Here inner() needs to remember what outer() is. outer() runs and returns inner(), you can see that greeting is not within the scope of inner(). So the web browser will look at the code and see the inner() need greeting so it's going to remember it. So after running newFunc(). An alert Hi will pop up. even though outer() is never going to be run again the only thing that's left is the function inner() the web browser remembers greeting.

When to use Closure?

The closure is useful in hiding implementation detail in JavaScript. In other words, it can be useful to create private variables or functions.

The following example shows how to create private functions & variables.

var count = (function() {
  var privateCount = 0;
  function changeBy(val) {
    privateCount += val;
  }
  return {
    increase: function() {
      changeBy(1);
    },
    decrease: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCount;
    }
  };   
})();

alert(count.value()); // 0
count.increase();
count.increase();
alert(count.value()); // 2
count.decrease();
alert(count.value()); // 1

In the above example, increase(), decrease() and value() becomes public function because they are included in the return object, whereas changeBy() function becomes private function because it is not returned and only used internally by increase() and decrease().

Summarizing

Closures are just saying, A function ran, the function executed. it's never going to execute again. But it's going to remember that they're references to those variables, So the child scope it's always going to have access to the parent scope.

  • Returning a function from inside another function is the classic example of closure, because the state inside the outer function is implicitly available to the returned inner function, even after the outer function has completed execution.

  • A closure is created when a function is declared; this closure is used to configure the execution context when the function is invoked.

  • A new set of local variables is created every time a function is called.