JavaScript Closures 101- they're not magic
Credits: This tutorial is written by Morris Johns. Morris maintains a personal blog called Developing Thoughts where he can be contacted via.
This tutorial explains closures so that a regular programmer can understand them - using working JavaScript code. It is not for gurus nor functional programmers.
Closures are not hard to understand once the core concept is grokked. However, they are impossible to understand by reading any academic papers or academically oriented information about them!
This article is intended for programmers with some programming experience in a main-stream language, and who can read the following JavaScript function:
function sayHello(name){ var text = 'Hello ' + name; var sayAlert = function(){ alert(text); } sayAlert(); }
An Example of a Closure
Two one sentence summaries:
- a closure is the local variables for a function - kept alive after the function has returned, 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!)
The following code returns a reference to a function:
function sayHello2(name){ var text = 'Hello ' + name; // local variable var sayAlert = function(){ alert(text); } return sayAlert; }
Most JavaScript programmers will understand how a reference to a function
is returned to a variable in the above code. If you don't, then you need to
before you can learn closures. A C programmer would think of the function as
returning a pointer to a function, and that the variables sayAlert
and say2
were each a pointer to a function.
There is a critical difference between a C pointer to a function, and a JavaScript reference to a function. In JavaScript, you can think of a function reference variable as having both a pointer to a function as well as a hidden pointer to a closure.
The above code has a closure because the anonymous function function() { alert(text); }
is declared
inside another function, sayHello2()
in
this example. In JavaScript, if you use the function
keyword inside another function, you are creating a closure.
In C, and most other common languages after a function returns, all the local variables are no longer accessible because the stack-frame is destroyed.
In JavaScript, if you declare a function within another function, then
the local variables can remain accessible after returning from the
function you called. This is demonstrated above, because we call the
function say2();
after we have returned from
sayHello2()
. Notice that the code that we call
references the variable text, which was a
local variable of the function sayHello2()
.
function() { alert(text); }
Click the button above to get JavaScript to print out the code for the
anonymous function. You can see that the code refers to the variable
text. The anonymous function can reference
text which holds the value
'Jane'
because the local variables of
sayHello2()
are kept in a closure.
The magic is that in JavaScript a function reference also has a secret
reference to the closure it was created in - similar to how delegates are a
method pointer plus a secret reference to an object.
- JavaScript Closures 101- they're not magic
- More closures examples
- Summary of JavaScript closures