Closures are functions that refer to independent (free) variables (variables that are used locally, but defined in an enclosing scope). In other words, these functions ‘remember’ the environment in which they were created.

or

A closure is a stack-frame which is not deallocated when the function returns. (as if a ‘stack-frame’ were malloc’ed instead of being on the stack!)

Basic Example

const myFunc = (name) => {
  let string = name + ' says hello.'
  let sentence = () => {
    console.log(string)
  }

  return sentence
}

In the above example, all local variables that belong to myFunc become closures when myFunc is called, and sentence() is returned.

This means that even though myFunc() has been invoked, executed, and exited, the function sentence() still has access to myFunc’s local variables!

So lets call myFunc() and assign it to a variable. And then call the function it returns:

var henry = myFunc('henry')

henry() // => henry says hello.

myFunc() has now exited, but when we call henry(), we still have access to its local variable, sentence.

Real World Example

The following example shows how one can use closures to alert how many attempts remaining a user has to login.

See the Pen JS Closure Example by Henry Zhu (@hzhu) on CodePen.

In the example, I invoke warningInit() and assign the anonymous function that warningInit() returns to a new variable called warnUserWithAttempts

Now warnUserWithAttempts holds a function that remembers its parent’s local variable: attemptsRemaining. In this function, we also use a decrementor to mutate attemptsRemaining.

Now anytime a user submits in invalid email/password, we can call warnUserWithAttempts to alert them of their remaining attempts!