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.
To better understand closure, first there is something to know about lexical scope.
In languages with lexical scope (also called static scope), name resolution depends on the location in the source code and the lexical context, which is defined by where the named variable or function is defined. In contrast, in languages with dynamic scope the name resolution depends upon the program state when the name is encountered which is determined by the execution context or calling context.
One topic on stackoverflow offers two vivid examples (in C language):
For lexical scope:
The inner function
func2() have access to variable
x defined in outer function
For dynamic scope:
dummy1(); will print
dummy2(); will print
10. Dynamic scope search value according to the calling stack.
inner() will search variable
x in the context where it is defined, rather than the execution context.
It’s very common in SPA (single page application). For example, you need to implement a button which needs to remember how many times the user clicked. You can use closure as the callback:
In the book Single Page Web Applications, closures are used nearly everywhere. IIFE (Immediately Invoked Function Expression) is used to expose public API of a module, and encapsulate the private method:
In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument.
To make it simple, currying is to fill the function parameters by steps, and each time generates a more specific function, calculates the value when all the parameters are filled.
For example, we need a
sum() function, which take a sequece of numbers, and return the sum of them.
After currying it, we can evalute it as:
Here we can use closure to help remember the already filled arguments:
length property of a function specifies the number of arguments expected by it.
So, we can implement currying for functions with fixed number of arguments:
Uncurrying is the dual transformation to currying, and can be seen as a form of defunctionalization. It takes a function f whose return value is another function g, and yields a new function f′ that takes as parameters the arguments for both f and g, and returns, as a result, the application of f and subsequently, g, to those arguments. The process can be iterated.
In another sense, uncurrying is the process to make a specific function more generic: In currying, we fill part of arguments of a function and create a new more specific function; In uncurrying, we take the specific function, and unfill the already filled arguments to make it more generic. Let’s see an example.
forEach methods of
Array.prototype are only available on array objects. Often we borrow it from array object to help the array-like work well:
Although it works, it looks very strange, and with uncurrying we can generate a generic function whose first argument is the object (the context), thus make the whole process more intuitive:
Now we can call them like this:
The trick is whether the
timeoutID returned by
setTimeout is set. If it’s set, it means there is one pending execution, and we should wait. In the callback of
setTimeout, we clear the
timeoutID to manifest that the work is done.
You can paste the following code snippet into your browser’s console and play with it:
Imagine you are implementing a chat application to talk to your Facebook friends and you have over 1000 friends online. If you load them at the same time, too much DOM operation will make the web page slow or even dead. Here is the point, we can separate all your friends into chunks, and add one chunk every second:
The following code snippet print 2 numbers every second:
There are still some common mistakes you’ll meet, even though closure is powerful.
i will be
5, and each function in
fArr will print
One way to sovle this problem is to create a closure in each iteration of the loop:
Another solution is to use the
let keyword in es 6, and in every iteration a new local variable
i is created:
In non-strict mode,
this in callbacks of
setInterval points to the
window variable, and it’s
undefined in strict mode. Look at the example below, we need make the bird tweak for 3 times at given frequency.
It failed because
this in the callback function of
window, one solution to this is to use
bind to remember
Though it’s not a problem directly related to closure, we can use closure to sovle it. Just keep
this in variable
self, and the callback of setInterval is a closure thus can visit
- encapsulate private variable or function
- currying: fill arguments by steps
- uncurrying: create a more generic function
- throttling: control the frequency of calling a function
- execution in chunks: separate a big task into small parts
And finally some gotchas and their solutions are discussed: the loop variable and
this in the callbacks of
One more thing needs to be mentioned here: although closure is powerful, it did face some efficiency issue, e.g. the memory leak and creating new functions each time compared to the object-oriented paradigm. Also, too many levels of nesting is hard to understand and maintain, as the zen of Python puts it:
Flat is better than nested.
It’s better to think twice before wielding closures.