support@90-10.dev

JavaScript Closures

JavaScript closures are a powerful and essential feature of the language, often seen as a mysterious and confusing concept for developers.

What is a Closure?

In simple terms, a closure is a function bundled together with its lexical scope (referencing environment). This allows the function to "remember" the variables it had access to at the time it was created, even after the outer function has completed its execution. Closures enable JavaScript to handle functions as first-class objects, making it possible to use them as arguments and return values, as well as assigning them to variables.

Understanding Lexical Scope

To comprehend closures, you must first understand lexical scoping. Lexical scope is a mechanism that determines how variables are accessed and resolved within nested functions. In JavaScript, the scope of a variable is determined at the time of writing the code, not during its execution. This means that "inner" functions have access to the variables declared in their containing, "outer", functions even after the outer functions have completed their execution.

Practical Example

The outer function below is returning a reference to an inner function, which is then assigned to the variable greet. When we call greet, it uses the value of the name variable, even though the outer function has already completed its execution. This is possible because the inner function has access to its containing function's scope, thus forming a closure:

function outer() {
  const name = "Charlie";

  function inner(timeOfDay) {
    console.log(`Good ${timeOfDay} ${name}`);
  }
  return inner;
}

const greet = outer();
greet('Morning');   // prints: "Good Morning Charlie"

Use Cases

Encapsulation and Private Variables

Closures enable us to emulate private variables and methods in JavaScript, providing encapsulation and protecting data from being accidentally modified:

function outer() {
  const name = "Charlie";

  function inner(timeOfDay) {
    console.log(`Good ${timeOfDay} ${name}`);
  }
  return inner;
}

const greet = outer();
greet('Morning');   // prints: "Good Morning Charlie"