Closures - Javascript

·

3 min read

Closures are a fundamental JavaScript concept that every serious programmer should know function of closure.

In programming languages, closures (also lexical closures or function closures) are techniques for implementing lexically scoped name binding in languages with first-class functions. Operationally, a closure is a record storing a function[a] together with an environment:[1] a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created.[b]

function makeFunc() {
  const name = 'Hii';
  function displayName() {
    console.log(name);
  }
  return displayName;
}

const myFunc = makeFunc();
myFunc();

Running this code has exactly the same effect as the previous example of the init() function above. What's different (and interesting) is that the displayName() inner function is returned from the outer function before being executed.

At first glance, it might seem unintuitive that this code still works. In some programming languages, the local variables within a function exist for just the duration of that function's execution. Once makeFunc() finishes executing, you might expect that the name variable would no longer be accessible. However, because the code still works as expected, this is obviously not the case in JavaScript.

The reason is that functions in JavaScript form closures. A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time the closure was created. In this case, myFunc is a reference to the instance of the function displayName that is created when makeFunc is run. The instance of displayName maintains a reference to its lexical environment, within which the variable name exists. For this reason, when myFunc is invoked, the variable name remains available for use, and "Mozilla" is passed to console.log.

Now let’s see an example of closure within a loop. In this example we would to store a anonymous function at every index of an array.

// Outer function
function outer()
{
    var arr = [];
    var i;
    for (i = 0; i < 4; i++)
    {
        // storing anonymous function
        arr[i] = function ()
 { return i; }
    }

    // returning the array.
    return arr;
}
var get_arr = outer();

console.log(get_arr[0]());
console.log(get_arr[1]());

Lexical Environment

Every execution context has a reference to its outer environment, and that outer environment is called Lexical Environment.

When javascript asked for the value of var a in function two’s execution context it couldn’t find it so it moved down and searched in its outer lexical environment i.e. global execution context.

var a is not defined in function two so it searched in its lexical environment i.e. global execution context.

function init() {
  var name = 'Mozilla'; // name is a local variable created by init
  function displayName() {
    // displayName() is the inner function, a closure
    console.log(name); // use variable declared in the parent function
  }
  displayName();
}
init();

init() creates a local variable called name and a function called displayName(). The displayName() function is an inner function that is defined inside init() and is available only within the body of the init() function. Note that the displayName() function has no local variables of its own. However, since inner functions have access to the variables of outer functions, displayName() can access the variable name declared in the parent function, init().