DEV Community

Cover image for JavaScript Closures Explained with Interactive Demos
BeyondIT
BeyondIT

Posted on

JavaScript Closures Explained with Interactive Demos

Understanding The Scope (Backbone Closures)

The JavaScript uses the lexical scoping of variables. Simply the placement of the variable will determine who can access it. The access to the variable does not depend on how and when the code runs. Javascript determines the access of variables at compile time itself.

Read More, Check out the interactive demo here

Hierarchy of Scope In Javascript

  • Global Scope
    This are the variables which are accessible by all functions. We define them at the outermost place in our code structure.

  • Function Scope
    These are the variables which we define inside the function (With var keyword). They are only accessible inside the function and children functions in which we define the variable.

  • Block Scope
    The ES6 module provides us the block scope variable. These are the variables which we define inside any pair of curly braces { }. (using keywords let and const).

JavaScript Closures Explained with Interactive Demos

Understanding The Closures (Function's Backpack)

function exFunctionA() {
  const outerVariable = "I'm from the outside!";

  function exFunctionB() {
    console.log(outerVariable); // Accesses the variable from its "backpack"
  }

  return exFunctionB;
}

const myClosure = exFunctionA(); // outerFunction runs and is gone...
myClosure(); //...but innerFunction still has its backpack! Logs "I'm from the outside!"
Enter fullscreen mode Exit fullscreen mode

Read More, Check out the interactive demo here

JavaScript Closures Explained with Interactive Demos

The best analogy to understand closures is Backpack.

  • Think when we define any function (Function A), we define some variables inside it (lexical scope). Here we define the variable outerVariable inside Function A.
  • Think, to remember this information, functions create a backpack and hold all these values inside it.
  • Then again we define another function (Function B) inside our parent function (Function A). The Function B has access to the variable defined in the parent function (Function A).
  • So now our inner function will create a backpack and hold all this information.

When our outer function (Function A) executes and returns its context and lexical scope also finishes. But remember our inner function (Function B) has its own backpack, and inside the backpack it has the variable from the parent Function A (which is already executed).

Now this phenomena, after the execution of parent Function A and lapsing of its lexical scope. Our inner Function B can still access the variable which was defined inside the parent Function A is called Closures.

A closure = (function + its lexical environment)


Practical Uses of Closures

Read More, Check out the interactive demo here

JavaScript Closures Explained with Interactive Demos

1. Encapsulated counters

For example, we create a function createCounter(). We declare variable count inside it. We also declare another function increment() which uses the count variable. createCounter() function returns increment() function.

Now the createCounter() returns us the increment function. The increment function has access to the count variable. We can use the increment() function and change the value of the count variable. This allows use to encapsulate variables and avoid polluting our code.


2. Private variables & Module pattern

As per our earlier conversation in the above example. We can create a private variable inside a function. And returns an inner function which has access to variable. This hides the variable from direct access. This allows use to create private API without exposing state of private variable.


3. Event handlers / Callbacks

Closure helps us to preserve the context of asynchronous code. If we attach a callback with a variable from an outer scope, the closure preservers the variable. The callback can access the variable from the outer scope, even the parent function returned way back.


4. Iterators / Generators

We can create iterators or generators (inner functions) which can remember their progress using closure.


Conclusion

In simple words, closures are the function with awareness of their lexical scope.
We can leverage this utility for many use cases, some of the use cases we discussed.
If you know how to use closures more effectively, please comment down.

Top comments (0)