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.
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!)
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:
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.
In the example, I invoke
warningInit() and assign the anonymous function that
warningInit() returns to a new variable called
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!