Closures in JavaScript

Closures in JavaScript

Introduction

To understand closures, we first have to understand Lexical Environment and Scoping.

Lexical Environment

The Lexical Environment refers to the context within which JavaScript code is executed. This context includes where the code is written and its surrounding environment.

Consider the following example:

function myFunction() {
  let a = 1;

  function innerFunction() {
    console.log("Hello", a);
  }

  innerFunction();
}

In this example, innerFunction can access the variable a because it's inside myFunction, which contains innerFunction. The lexical environment includes all variables and functions that can be reached in the current area and its parent scopes.

Lexical Scoping

Lexical Scoping means that a variable's scope depends on where it is in the source code.

Here's an illustration:

function myFunction() {
  let a = 1;

  function innerFunction() {
    console.log("Hello", a);
  }

  return innerFunction;
}

const returnedFunction = myFunction();
returnedFunction(); // Accesses `a` even outside its defining scope

In this example, innerFunction is executed outside of myFunction, yet it keeps access to a. This happens because of closures.

Closures Explained

When myFunction is called, it creates a new environment that has a. By returning innerFunction, it keeps access to myFunction's environment. This ongoing access is what we call a closure.

A closure happens when a function can remember and use its original scope, even if it's run outside of that scope. This means innerFunction keeps the scope of myFunction, letting it access a no matter where innerFunction is called, even in another file.

This isn't possible in all programming languages.

Practical Use Cases

Closures are not just a theoretical aspect of JavaScript, they have practical use cases:

  • Data Encapsulation: Closures allow for private variables that cannot be accessed directly from outside the function.

  • Factory Functions: They can be used to create function factories that can create multiple instances of similar functions, each with access to private variables.

  • Event Handlers and Callbacks: Closures are widely used in event handlers and callbacks, where specific variables need to be accessed.