DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for JavaScript Basics-Closures
Debarshi Bhattacharjee
Debarshi Bhattacharjee

Posted on

JavaScript Basics-Closures

In the previous post, we learnt about of JavaScript Basics- Scopes & Hoisting.

We saw how variables and functions in local/function scope and block scope get restricted within that scope (they cannot be accessed outside the scope).

In this post, we'll learn how the opposite is true, how we can have access to all variables and functions present in the parent scope, from the child scope.

Some basics first

Lexical Scope in JS:

Lexical scope is the ability of a child function where it has to access all variables present in its parent's scope. The child function is said to be lexically bound to the scope of the parent function.

Example :

//Global Scope
var message="Hello JavaScript!"; // Can be accessed anywhere in 
                                    the program

function foo(){  // Function scope
  // Within the scope of foo

  var greet = "Hello World!";
  let number = 45;

  function baz(){ // Another Function Scope, lexically bound to 
                     the scope of foo and has access to all 
                     variables present in the scope of foo.


   console.log(greet); // Prints 'Hello World!'

   console.log(number); // Prints '45'

  }

baz(); // Called baz within the scope of foo

}
Enter fullscreen mode Exit fullscreen mode

In the above example, the child function baz declared within the scope of parent function foo has access to all the variables declared in foo's scope. This was possible as baz was lexically bound to the scope of foo.

Closures

A closure is a feature in JavaScript in which a child function has access to the parent function’s scope even when the function is executed outside its lexical scope.

According to MDN:

A closure is a special kind of object that combines two things: a function, and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created.

Any function that forms a closure has access to three scopes:

  • Its own scope β€” variables defined between its curly brackets

  • Parent scope- variables and function defined in parent
    function.

  • Global scope - global variables and functions

Example :

function outer(){
let count=0; // Declared in outer scope

   function increment(){ 
     count++;
     return count; // accessing count from parent scope 
   }
 return increment; // returning the increment method;
}

Enter fullscreen mode Exit fullscreen mode

Here we have two functions:

  • A parent function called outer which has a
    variable count assigned to 0, and returns an
    inner function increment.

  • A child function increment which is lexically scoped and
    forms a closure.

  • As the child function forms a closure it has
    access to all three scopes - its own scope, parent
    scope and the global scope.

We now invoke the parent function outer and store the returned function to variable x:

// Calling in global scope

const x = outer(); // assigned the function increment to 
                          variable x

console.log(x); // Prints the returned function increment

console.log(x()); // invoked the function increment for the first                 
                  // Prints 1;

console.log(x()); // invoked the function increment second time, 
                  // Prints 2;
Enter fullscreen mode Exit fullscreen mode

Here's what's happens now :

  • We invoked the function outer which initialized the variable
    count to 0 and assigned the returned function increment
    to variable x.

  • Logging x to console, prints the body of returned function
    increment.

  • We now invoke and log x for the first time, it increases the
    value of count form parent scope by 1 and returns it.

  • Invoking x for the second time, increases the previous value
    of count again by 1 and returns it.

In the above example, we saw that even though the child function increment was executed outside its parent's scope, it was able to remember the value of the variable count and increased its previous value exactly by 1 one each call. This was possible because the function increment had formed a closure.

Conclusion:

Closures are one of those tricky concepts in JavaScript that are difficult to grasp at first. But once you understand them, you realize that things could not have been any other way.

Resources

MDN

Top comments (2)

Collapse
amt8u profile image
amt8u

Just curious, why does closure exist? What if it is removed from the language?

Collapse
devdebarshi profile image
Debarshi Bhattacharjee Author

They help us to implement some key features in JS such as Data Hiding and Module Pattern. Hooks in React was possible due to Closures. I'll surely write another post on advantages and usage of closures.

πŸ”  Find your favorite font

Β 
You can change your default font in Settings.