techStackGuru

JavaScript Closure


Closures in JavaScript allow functions to access variables from their outer scopes even after the outer functions have completed. As a result, it creates a "snapshot" of the variables when the inner function is defined. It is common for closures to create private variables or to implement persistent functions.

Example

function createCounter() {
  let count = 0;

  function increment() {
    count++;
    console.log(count);
  }

  return increment;
}

const counter = createCounter();
counter(); // Output: 1
counter(); // Output: 2
counter(); // Output: 3 

Using the example above, the createCounter function returns an increment function. Whenever we call createCounter(), the count variable is created and the increment function is defined. As a result of closure, even after the increment function is returned and executed outside of its original scope, it still has access to the count variable.

When we call the counter function, its value is logged to the console and the count variable is incremented. As the count variable is enclosed within the scope of the createCounter function, it persists across multiple calls to the counter function.

When you need to create functions with private data, closures are particularly useful. Using the example above, the count variable is effectively private since it is not accessible outside of the createCounter function.

The use of closures enables advanced JavaScript techniques, such as currying, memoization, and module patterns. They allow more flexibility and modularity in code by encapsulating and maintaining state within a function.

Example 2

function outerFunction() {
    var outerVariable = "Hello";
  
    function innerFunction() {
      console.log(outerVariable);
    }
  
    return innerFunction;
  }
  
  var closureExample = outerFunction();
  closureExample(); // Output: "Hello" 

In the example above, the outerFunction declares an inner function innerFunction and a variable outerVariable. Afterward, the outerFunction returns the innerFunction. By assigning closureExample to outerFunction, outerFunction creates a closure where innerFunction has access to outerVariable.

Example 3

function counter() {
    var count = 0;
  
    return {
      increment: function() {
        count++;
      },
      decrement: function() {
        count--;
      },
      getCount: function() {
        return count;
      }
    };
  }
  
  var counterObj = counter();
  counterObj.increment();
  counterObj.increment();
  console.log(counterObj.getCount()); // Output: 2 

As shown in the example, the counter function returns an object having three methods: increment, decrement, and getCount. Within the counter function, these methods have access to the count variable. A count variable remains private and cannot be accessed or modified outside of the returned object.