{closure}

A JS Concept Worth Knowing


let count = 0

function addTwo(){
  return count * 2
}

AddTwo Function


let count = 0

// this function has access to the global count variable
function addTwo(){
  return count * 2
}

AddTwo Function

Closure

Functions nested inside a parent scope have access to the parent scope's variables, and even the grandparent scope and so on, up the chain, this is called closure.

let count = 0

function addTwo(){
  return count + 2
}
let count = 0

function addTwo(){
  return count + 2
}
// Global Scope
let count = 0

function addTwo(){
// Function Scope
  return count + 2
}

The addTwo Function has access to the count  variable in its parent, which is the global scope

let count = 0

function addTwo(){
  return count + 2
}

function addRandom(){
  let rand = Math.floor(Math.random() * 10)
  return count + rand
}
let count = 0

function addTwo(){
  return count + 2
}

function addRandom(){
  let rand = Math.floor(Math.random() * 10)
  return count + rand
}

The addTwo function DOES NOT have access to the rand variable

let count = 0
let rand = Math.floor(Math.random() * 10)

function addTwo(){
  return count + 2
}

function addRandom(){
  return count + rand
}
let count = 0
let rand = Math.floor(Math.random() * 10)

function addTwo(){
  return count + rand + 2
}

function addRandom(){
  return count + rand
}

Most times closure is created using a function inside a function

function outerFunc() {
  // the outer scope
  let outerVar = 'Number of times outerFunc has run';
  let count = 0;
  
  function innerFunc() {
    // the inner scope
    count++;
    return `${outerVar}: ${count}`;
  }
  return innerFunc;
}
function outerFunc() {
  let outerVar = 'Number of times outerFunc has run';
  let count = 0;
  
  function innerFunc() {
    count++;
    return `${outerVar}: ${count}`;
  }
  return innerFunc;
}

let myFunc = outerFunc();

innerFunc function is stored in memory in the variable myFunc

count and outerVar values are also stored with the function

The combination is called: closure

function outerFunc() {
  let outerVar = 'Number of times outerFunc has run';
  let count = 0;
  
  function innerFunc() {
    count++;
    return `${outerVar}: ${count}`;
  }
  return innerFunc;
}

let myFunc = outerFunc();
let first = myFunc() => Number of times outerFunc has run: 1
let second = myFunc() => Number of times outerFunc has run: 2

Where do I Use Closures?

let countClicked = 0;

myButton.addEventListener('click', function handleClick() {
  
  countClicked++;
  
  myText.innerText = `You clicked ${countClicked} times`;
});

Your myText block in your HTML would reveal the string with the number of times the button was clicked

let countEven = 0;
const items = [1, 5, 100, 10];

items.forEach((number) => {
  if (number % 2 === 0) {
    countEven++;
  }
});

countEven; // => 2
function NumChanger() {
  const [num, setNum] = useState(0);

  useEffect(() => {
    console.log(`You have clicked ${num} times`);
  }, [num]);

  return (
    <>
      <button
        onClick={() => {
          setNum(num + 1);
        }}
      >
        Increment
      </button>
    </>
  );
}

Interviews

Simply put:

A closure is a function that remembers the variables from the place where the variable is defined, regardless of where the function is executed.

- Dimitri Pavlutin

Code

By JD Richards