Closures in JavaScript - what and why we need closures?

Closures in JavaScript - what and why we need closures?

·

4 min read

What Is Closures in JavaScript?

Recently I saw lots of tweets and post about closures in JavaScript and I thought about posting about my understanding of the Closures.

According to MDN closure is "A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time."

So now you understand what closure is let's move on to next part, just kidding ;) to make it clear lets see an example, but before that I assume you are familiar with concepts such functions are first class citizen, call stack and scopes/execution context (if not please leave comment, I'll post blogs about functions, call stack and scopes/execution context).

function outer(){
    let closureVariable = 5;
    let nonClosureVariable = 7;
    return function inner(){
        return 5 + closureVariable;
    }
}

let inner = outer();
debugger;
inner();

In the example above you see that I have declared a function outer with two variables closureVariable and nonClousreVariable and returned a function inner which is accessing the closureVariable. You can also see that I have a debugger just before executing inner function.

image.png

When I run the code in chrome console, as you can see in the image, though the call stack is in inner function's execution context and outer function is kicked off from the call stack you can still access the closureVariablebut nonClosureVariable is not available, JavaScript knows what variable is needed for the execution of inner function and keep those variables in memory till the exection of inner function this is clousure. In simple words

The ability of JS function to keep the variables from outer scope in memory till it's execution.

I hope you can understand what closure is now let's move on to why we need closures.

Why we need closures? Or Where can we use closure?

There are many uses for closures, let us see 2 uses with examples.

  • Encapsulation
  • Function Composition

Encapsulation with closure:

Let's see an example of encapsulation with closure, let us build a function which keeps track of seconds passed.


// Encapsulation 
const calculateTime = () =>{
    let seconds= 0;
    const toAdd = 0.5
    let addSeconds= () => seconds+= toAdd // Arrow function implicit return
    setInterval(addSeconds,500); // Adding 0.5 second every 500 milliseconds 
    return ()=> seconds; // Arrow function implicit return
}

let timeStart = calculateTime();
// Assume function is a long running function that takes 5 seconds to execute.
setTimeout(()=>console.log(timeStart()),5000);

In the example above assume we're building a function to calculate time taken for execution of a function in different browser or computers.

Here you can see the calculateTime function returns the seconds inside a anonymous function and we've successfully encapsulated all the implementation details and we're just returning the seconds variable but the function has access to other variables such as toAdd and setInterval but from outside the function we can only access the seconds variable.

Note: I'm using arrow function just to show arrow function supports closure, we can use normal function also

Compose with closure:

Lets see an example of composing function with closure

function addWith(num1){
    return num2=> num1 + num2 // Arrow function with implicit return
}

const addWithFive = addWith(5);// Closure function remembering 5
const addWithTen = addWith(10);// Closure function remembering 10
const addWithEight= addWith(8);// Closure function remembering 8
console.log(addWithFive(7));
console.log(addWithTen (7));
console.log(addWithTen (7));

In the example above we're composing 3 new functions addWithFive,addWithTen and addWithEight with help of addWith function. This is possible because of the closure as the functions can keep track of the num1 we're able to use the composition.

Conclusion

The examples I gave above are silly but I hope you can see the power of closures now. In short

  • Closure let's the inner function keep track of variable outside of it's scope.
  • Especially useful for encapsulation and composing function from other functions.
  • Keeps track of value even after the outer function is out of the call stack.

If you enjoyed the article please share it with others, feel free to hit me up on twitter

This is my first blog post so please leave your valuable comments. If you find any topic in this post difficult to understand let me know I'll write about it.