Closure In JavaScript

All you need to know about Closure In JavaScript

What is closure?

Closure is a fundamental concept in JavaScript, which enables functions to remember and access their lexical scope even when they are executed outside of that scope. It occurs when a function retains access to variables from its outer scope even after the outer scope has finished executing.

Let's understand two vital concepts.

1: What is lexical scope?
2: What does it mean for a parent function to have finished expecting?

Let's understand lexical scope with examples

Lexical scope defines how variable names are resolved in nested functions.

Imagine you have a set of nesting dolls. Each doll is placed inside another. The smaller doll can see and access everything within the doll it's placed in, as well as everything outside.

In programming terms:

  1. Outer Scope: This is like the larger nesting doll. It contains variables and functions.

  2. Inner Scope: This is like the smaller nesting doll inside the larger one. It can access its own variables as well as those in the outer scope.

Examples

Lexical Scope with Global Variable

let globalVariable = 'I am global';
function myFunction() {
    console.log(globalVariable); // Accessing globalVariable
}
(); // Output: "I am global"

In this example, globalVariable is defined in the global scope. Any function defined within this scope has access to globalVariable directly.

Example 2

Lexical Scope in Nested Functions

function outer() {
    let outerVar = 'Outer Variable';
    function middle() {
        let middleVar = 'Middle Variable';
        function inner() {
            console.log(outerVar + ' ' + middleVar);
        }
        inner();
    }
    middle();
}
outer(); // Output: "Outer Variable Middle Variable"
console.log(middleVar); // Output: ReferenceError: middleVar is not defined

Here, inner has access to both outerVar from its outer scope (outer) and middleVar from its immediate outer scope (middle) but cannot be accessed outside the middle function. This showcases how lexical scope works with nested functions.

So, lexical scope is all about where you place your variables in your code and how that affects where they can be accessed. It's a fundamental concept in understanding how JavaScript (and many other programming languages) handles variable visibility and accessibility.

What does it mean for a parent function to have finished expecting?

When a function finishes executing, its local variables and scope are typically destroyed or garbage collected. However, if there are inner functions (child functions) defined within the parent function, and those inner functions have been returned or are still in scope elsewhere in the program, they can maintain references to the variables in the parent function's scope. This is what creates a closure.

So when we say, "Closure, is a function that has access to the parent scope, even after the parent function has closed," What do we mean?

This means that the inner function maintains a reference to the variables and parameters of the outer function's scope, allowing it to access and manipulate them even after the outer function has completed execution and its local variables should technically be out of scope.

Example

Consider the following scenario:

function outerFunction() {
  let outerVariable = 'I am from the outer function';
  function innerFunction() {
    console.log(outerVariable);
  }
  return innerFunction;
}

const innerFunc = outerFunction();
innerFunc(); // Output: I am from the outer function

In this example, outerFunction defines a variable outerVariable and also declares an inner function innerFunction that logs the value of outerVariable. innerFunction is then returned from outerFunction.

Now, when outerFunction is called and assigned to innerFunc, it actually returns innerFunction. But what's interesting is that even after outerFunction has finished executing and its execution context has been destroyed, innerFunction still retains access to the variables within its parent scope (i.e., the scope of outerFunction).

This behavior is what we refer to as closure. The inner function (innerFunction) has access to its parent function's scope (lexical scope), even after the parent function (outerFunction) has completed execution and been removed from the execution stack.

To understand this better, let's break down the process:

  1. When outerFunction is called, a new execution context is created with its own scope chain.

  2. Inside outerFunction, innerFunction is defined, which creates a closure over the outerVariable.

  3. When innerFunction is returned from outerFunction and assigned to innerFunc, it maintains a reference to its lexical environment, which includes the outerVariable.

  4. Later, when innerFunc is invoked, it still has access to the outerVariable because of the closure created during its creation.

Why do you need to understand the concept of closure?

Closure is important in JavaScript because it enables encapsulation, data privacy, and the management of asynchronous operations. With closures, you can create private variables and functions, control access to sensitive data, and maintain the integrity of your code. Closures are crucial for managing asynchronous operations, implementing callbacks, and event handling. They also allow for the dynamic generation of functions and provide a powerful tool for building modular and maintainable code. Understanding closures is essential for writing clean, efficient, and secure JavaScript applications.

Thank you ☺️ for taking the time to read. If you're interested in exploring similar topics further, I invite you to connect with me on LinkedIn and Twitter.

LinkedIn: https://www.linkedin.com/in/garuba-abdul-azeez-713273167/

Twitter: https://x.com/devAzeezjim?s=09

πŸ‘‹πŸΌπŸ‘‹πŸΌπŸ‘‹πŸΌ

Β