First understand scope; said old closure

First understand scope; said old closure

let age = 10;
console.log(age); // logs 10

Scope manages the accessibility of variables. Since the definition of age (line # 1) & accessing it (line # 2) are within the same scope. It works!

In JavaScript, a new scope is created by a function or a code block.

What about different scopes?

function main() {
 // defined in function scope
 let num = 0;
 console.log(num) // 0
}
// accessing it in global scope
console.log(num) // ReferenceError: num is not defined (because different scopes)

So, variables defined in a scope are not accessible in a different scope.

But wait:

function outer() {
 // outer function scope
 let outerNum = 0;
 console.log(innerNum); // ReferenceError: innerNum not defined
 function inner() {
 // inner function scope
  let innerNum = 1;
   console.log(outerNum); // 0. Works, lexical scoping
 }
 inner();
}
outer();

Take notes!

  1. Scopes can be nested

  2. The inner scope has access to outer scope/s variables (outerNum) but outer scope cannot access inner scope/s variables. That's called lexical scoping

  3. The lexical scope of inner consists of outer scope & global scope

But where are closures?

function outer() {
 // lexical scope = outer's scope + global scope
 const outer = 1;
 function inner() {
   const inner = 2;
   // lexical scope = inner's scope + outer's scope + global scope
   console.log(outer + inner)
 }
 inner(); // calling from outer's scope which is the lexical scope for inner
}
outer():

Notice the inner() call which is happening in the outer function's scope i.e lexical scope of the inner. That will work

Let's call Inner from a different scope!

function outer() {
 const outer = 1;
 return function inner() {
   const inner = 2;
   console.log(outer + inner)
 }
}

{
    // A new scope, which isn't the lexical scope of inner
    const innerFunc = outer(); // returns `inner`
    innerFunc();
}

Since now we are using the inner function in a different scope (which isn't it's nested scope), would it still work? considering that it is using a variable (outer) from it's lexical scope?

The answer is yes! And that's what closure is

The closure is a function that accesses its lexical scope even executed outside of its lexical scope.

In our case, inner() is a closure since it's accessing outer variable from it's lexical scope within another scope which isn't inner's lexical scope!

Credits

Please do visit Dmitri's Article on Closures which inspired me to start writing.