Closures in JavaScript

  • 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 (its variables) from an inner function, even after the outer function is removed/returned from the stack.
     
  • Closure is a JavaScript property, which ensures that a function remembers the environment in which it was created.

Closures in JavaScript

Closures in JavaScript

function outer() {
  const outerConst = 300;
  
  function inner() {
    console.log(outerConst)
    const innerConst = 500;
  }
  
  console.log(outerConst)
  inner()
  console.log(outerConst)
}

outer()
  • The inner function gets access to the variables of the outer function,
     
  • But the outer function does not has access to inner function

Closures in JavaScript

  • Because of closures, although the outer function is done or has returned, its variables can still be accessed by the inner function.
     
  • Now if the inner function is accessed outside the outer function, it can still access the outer function's variables.
     
  • Because closure of a function is created exactly when that function is created
function outerWrapper() {
  let counter = 0;
  
  function incrementCounter() {
    counter++
    return counter
  }
  
  return incrementCounter
}

const counterInc = outerWrapper()
counterInc() // 1
counterInc() // 2
counterInc() // 3

Closures in JavaScript

const globalValue = "I'm global"

function outer() {
  const outerConst = 300;
  console.log(globalValue)
  
  return function inner() {
    console.log(outerConst, globalValue)
    const innerConst = 500;
  }
}

const innerFunc = outer()
innerFunc()
  • The inner function has access to all the variables which are defined in outer function,
  • Also the variables to which outer function has access (globalValue)are also accessible to the inner function

Closures in JavaScript

function outer(firstName) {
  const outerConst = 300;
  console.log(firstName, lastName)
  // Reference Error: 'lastname' is
  // not defined
  
  return function inner(lastName) {
    console.log(firstName, lastName)
    const innerConst = 500;
  }
}

const innerFunc = outer("Yash")
innerFunc("Priyam")
  • The arguments that the outer function receives, are also accessible to the inner function.
  • The arguments that the inner function receives, are not accessible to the outer function.

Closures in JavaScript

  • Any function generally has 3 scopes:
    - its own scope:  local scope
    - its enclosing scope: closure scope
    - and lastly: global scope
function makeAdder(x) {
  const zero = 0;
  
  return function (y) {
    return x + y + zero;
  };
}

const add5With = makeAdder(5);
const add10With = makeAdder(10);

console.log(add5With(2)); // 7
console.log(add10With(2)); // 12

Scope Chain

Closures in JavaScript

  • We can have multiple nested functions, each inside the other.
  • Now each inner function will have access to all the variables in the scope of its outer function/s.
  • The scope of all of these nested functions are connected like a chain, called a Scope Chain.
  • Now even though an outer function is done/returned, its variables will remain a part of scope chain for the inner functions to be able to access them.
// global scope
const e = 10;
function sum(a) {
  return function sum2(b) {
    return function sum3(c) {
      // outer functions scope
      return function sum4(d) {
        // local scope
        return a + b + c + d + e;
      };
    };
  };
}

const sum2 = sum(1);
const sum3 = sum2(2);
const sum4 = sum3(3);
const result = sum4(4);
console.log(result); // 20

Scope Chain

Closures in JavaScript

// global scope
const e = 10;
function sum(a) {
  return function (b) {
    return function (c) {
      // outer functions scope
      return function (d) {
        // local scope
        return a + b + c + d + e;
      };
    };
  };
}

console.log(sum(1)(2)(3)(4)); // 20

Scope Chain

  • The same code can also be written with anonymous functions, like this:
  • This pattern (line 15), is also called as currying pattern.