What are Closures in JavaScript?

What are Closures in JavaScript?

·

6 min read


Let's go Zero to Hero in JavaScript closures. Some tough stuff is here! Let's go on...


Closures is the boss of the game. However, it's impossible to even understand what is it, without first understanding things like the scope chain, lexical environment and how exactly your JavaScript is being executed. You use them, but you don't even know they're called closures.

'Closures' are not a tool, they are a concept which if you came to understand, you're going to look at the language in a much different way as I did 😐. I am not going to throw you the right way in the deep, we're first preparing your mind for the closures blow up by taking a look at some other needed concepts (Dependencies).


Scope

The scope is where the variable is accessible in your code during runtime.

let a = 5; 
console.log(a); //5
// The above code declared in the global scope. Variables declared in the same scope have access to one another. 
const bla = () => {
    // each time you create a new function, you create anew scope called function scope. 
    let bb = 6; 
    console.log(a); // 5 (function scope has access to the global scope)
}
console.log(bb) // error (global scope does not have access to the function scope)

Execution context

Execution contest is the scope the current code is running in. When we start a program, first it has a global execution context. When a function is called, JavaScript creates a new execution context - a local execution context, which has its own set of variables which are local to this execution context.

When a 'return' statement or a closing bracket '}' is encountered, the function passes the returned value (or undefined if '}' ) to the contest where it was called. The local context for the function is deleted (with all of it's variable), which makes them not available anymore.


Lexical scope

Examples:

const bla = () => {
    let a = 48; 
    const gg = () => {
        console.log(a); 
    }
    gg();
}
bla() // 48

What's important here is that the function gg has access to a. But a is in the calling context of gg (the scope from where gg is called). IMPORTANT -> A function has access to variables that defined in its calling context. The formal name of this phenomenon is "lexical scope".

Function returning function

const createAdder = () => {
    const addNumber = (a, b) => {
        let ret = a + b 
        return ret
    }
    return addNumber
}
let adder = createAdder()
let sum = adder(3, 2)   // 5

What is important to understand here is that a function definition can be stored in a variable, and it's invisible to the program until it gets called. Once this is done, a local execution context is temporarily created. This context dies when the function is done.


JavaScript closures

All the dependencies declared and explained, let's dive into the real topic, we've all been waiting for!

const counterNew = () => {
    let counter = 0; 
    const func = () => {
        counter = counter = 1; 
        return counter; 
    }
    return func; 
}
let incr = counterNew(); // returns a function 
incr() // 1
incr() // 2
// Ah!! How it get incremented?

The answers are simple - closures.

What are closures?

"A closure is a function which has reference to it's the lexical environment. This environment consists of any local variables that were in-scope at the time the closure was created!' - MDN Docs

Go back to the counterNew function. Try to understand it, read all again, do your research. Closures are not like "Yayay I got it!" It's considered as an advanced topic, so take your time (as I am taking) and think.

What you'll notice is that by the rules you have, there's no way that this counter variable would be remembered and incremented each time. The missing part of the puzzle I called closures.


🙂Thanks For Reading | Happy Coding😎

Did you find this article valuable?

Support Rahul by becoming a sponsor. Any amount is appreciated!