Closures in JavaScript, a Quick Primer

“To page authors coming from a traditional OO (object oriented) or procedural programming background, closures are often an odd concept to grasp, whereas to those with a functional programming background, they’re a familiar and cozy concept.”

Bibeault and Katz at 428-29.
Chapter on Closures in JavaScript Ninja Book

Definitions of “Closures”

Q.: Just what is a “closure”? Is it a function? A scope? An object?

A.: Yes.

“A closure is a special kind of object that combines two things: a function, and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created.”

Closures have also been called

“the scope created when a function is declared that allows the function to access and manipulate variables that are external to that function. Put another way, closures allow a function to access all the variables, as well as other functions, that are in scope when the function itself is declared.”

Resig and Bibeault at 90.

Put yet another way, a “closure is a Function instance coupled with the local variables from its environment that are necessary for its execution.”

Bibeault and Katz at 429.

“A function declaration and its environment form a closure allowing the function, when later invoked, to access those local variables that become part of the closure.”

Bibeault and Katz at 431.

In most languages,
“when a function is declared, it has the ability to reference any variables that are in its scope at the point of declaration. . . . With closures, these variables are carried along with the function even after the point of declaration has gone out of scope, closing the declaration.”

Bibeault and Katz at 429.

“In other words, the function defined in the closure ‘remembers’ the environment in which it was created.” MDN. This is one of the “good parts” of JavaScript: With nested functions, “inner functions get access to the parameters and variables of the functions they are defined within (with the exception of this and arguments). Crockford at 37.

Syntax

A popular closure answer on Stack Overflow shows the following example syntax:

function foo(x) {
    var tmp = 3;
    function bar(y) {
        alert(x + y + (++tmp)); // will alert 16
    }
    bar(10);
 }
foo(2);

“This will always alert 16, because bar can access the x which was defined as an argument to foo, and it can also access tmp from foo.

That is a closure. . . . Simply accessing variables outside of your immediate lexical scope creates a closure.”

Note that the above example features an inner function and an outer function – when you see nested functions, it should trigger thoughts of closures.

Implications for Development

“While scores of page authors get along writing on-page scripts without understanding the benefits of closures, the use of closures can not only help us reduce the amount and complexity of the script necessary to add advanced features to our pages, they allow us to do things that would simply not be possible, or would be too complex to be feasible, without them.”

Resig and Bibeault at 89.

In other words they have an “ability to drastically simplify complex operations.” Id.

For example, “the ability for callback functions to reference the local variables in effect when they were declared is an essential tool for writing effective JavaScript.” Bibeault and Katz at 429.

Emulation of “Private” Methods through the Module Pattern

In JavaScript, methods cannot be declared “private,” meaning that they can only be called by other methods in the same class. However, this can be emulated in JavaScript, especially by using the module pattern. See MDN and Ben Cherry, “Module Pattern in Depth”. Also see Angus Kroll, “Function Delarations v. Function Expressions”.

Cautionary Notes

It is possible to inadvertently create closures in JavaScript as they can be created without explicit syntax (unlike in other languages). Bibeault and Katz at 430. This can cause issues.

Memory Leaks

“It is unwise to unnecessarily create functions within other functions if closures are not needed for a particular task, as it will negatively affect script performance both in terms of processing speed and memory consumption.” MDN. For example, “circular references can lead to memory leaks. A classic example of this is the creation of DOM elements that refer back to closure variables, preventing those variables from being reclaimed.” Bibeault and Katz at 430; also see IBM.

Creating Closures within Loops

Also, see MDN for an example of possible problems when closures are created within loops.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)