Picking up Javascript - Closures and lexical scoping
So much like the last one , this article is going to focus on a piece of the javascript language that I had trouble understanding, and may be a point of confusion for you. Today I’ll be looking at closures and lexical scoping. Last time, I mentioned that Javascript has more in common with functional languages, than classical languages. Today will be no different as closures and lexical scoping are two more features that come from the functional programming ancestry that Javascript has.
What’s a closure?
To understand what closure is you first need to understand stack-frames. In PHP a stack-frame is created each time a function is called.
- function sayHello($name) {
- $return = 'Hey there' . $name;
- return $return;
- }
- sayHello('Peter') //echos 'Hey there Peter'.
The above function when run will create a stack-frame for itself, and $return
will exist and be available inside that stack-frame. Once sayHello()
is done $return
vanishes into the garbage collector, and is gone until the next time sayHello()
is invoked. However, in Javascript we are able to declare inner and anonymous functions. These functions are enclosed by their containing function and are said to form a closure. A simple example of a closure is
- function sayHello(name) {
- var phrase = 'Hey there' + name;
- var sayHi = function() {
- alert(phrase);
- };
- return sayHi;
- }
- var talk = sayHello('Peter');
- talk(); //alerts 'Hey there Peter'
In Javascript functions still create stack-frames however, inner functions have access to any of the containing functions local variables. So a closure is a stack-frame that doesn’t go away after a function is complete. In the above Javascript sayHi
is an inner function of sayHello
. As we saw when we executed talk()
it still had access to the name
variable of its containing function. You create a closure in Javascript each time you put a function inside another function. Closures in Javascript preserve all the local variables that existed in the function when it completed. This phenomenon of local variable preservation is referred to as Lexical Scoping.
Ok, so what?
So by creating closures we can do a number of things. First off we can create visibility, something that many people seem to think Javascript lacks. The following example illustrates this.
- function Beer(type) {
- this.type = type;
- var volume = 0.5;
- var lessBeer = function() {
- volume = volume - 0.5;
- };
- this.drink = function() {
- if (volume === 0) {
- console.log('no more beer :(');
- return;
- }
- lessBeer();
- console.log('mmm beer.');
- };
- };
- var stout = new Beer('stout');
- console.log(stout.type); // prints 'stout'
- stout.drink(); //prints mmm beer
- stout.drink(); //prints no more beer :(
- stout.volume = 10; //trying to top up doesn't work!
- stout.drink(); //prints no more beer :(
- stout.lessBeer() //TypeError? must be private
If you run the above code in your favorite Javascript console You should get the results in the comments. What this illustrates is that you cannot fill a beer back up, and that by using closures you can create private variables and functions that cannot be accessed from outside the object. jQuery leverages closures extensively.
More on lexical scoping
Lexical scoping is a fancy term that refers to a function remembering and preserving its state between and after executions. However, lexical scoping in Javascript is not truly static, as the wikipedia may lead you to believe. A simple example of lexical scoping is
- var count = 5;
- function tellCount() {
- console.log(count);
- };
- tellCount(); //prints 5
- count = 7;
- tellCount(); //prints 7;
This shows how the local variables in a scope are preserved but the values will always reflect the most current values. While count
is contained inside the closure created by tellCount()
it updates to reflect the current value in the top most scope, which in this case is window
. This trick is useful and infuriating at times. If you’ve ever tried defining functions in a loop you’ve probably been dismayed to find out all the functions always reflect the last value in the loop.
So loops and lexical scoping will eventually cause you some grief. The quickest way to achieve this grief is by defining functions in a loop. Lets say you want to loop over an array and make links that say their value, seems easy right? Well until our good friend lexical scope shows up and drinks all the programatic beer. Take the following example.
- var numbers = [1, 2, 3, 4, 5];
- for (var i in numbers) {
- var num = numbers[i];
- var anchor = document.createElement('A');
- anchor.setAttribute('href', '#');
- anchor.appendChild(document.createTextNode(num));
- document.body.appendChild(anchor);
- anchor.addEventListener('click', function(event) {
- alert('My number is ' + num);
- event.preventDefault();
- }, false);
- }
If you run this in firebug’s console you’ll get five links, that have click events on them. However, each link will say ‘My number is 5’, all because of lexical scoping. The event listener uses a closure to refer to num
however, it doesn’t maintain the value of num
from when the function was declared but instead maintains the last know value of num
. Which just happens to be 5. Now most javascript libraries give you a good work around by allowing apply events to collections of elements. jQuery has $.each()
, and its $.bind()
and friends. Mootools has a similar construct in Element.addEvent
. However, if you need a loop variable inside an event one way to do it is to do the following:
- var numbers = [1, 2, 3, 4, 5];
- for (var i in numbers) {
- var num = numbers[i];
- var anchor = document.createElement('A');
- anchor.setAttribute('href', '#');
- anchor.appendChild(document.createTextNode(num));
- document.body.appendChild(anchor);
- var clicker = function(number) {
- return function (event) {
- event.preventDefault();
- console.log('My number is ' + number);
- };
- };
- anchor.addEventListener('click', clicker(num), false);
- }
Because the scope container in javascript is a function, you need to use additional functions to bind variables to different scopes. In the above example we use the function clicker
to make a closure that contains the correct value for num
which becomes number
in the closure.
So that’s all for today. Lexical scoping and closures can be a tricky subject to grasp but once you do, they are a powerful feature of the language that you will wonder how you lived without.
Great article, very interesting. Love the beer example! =)
Nick on 2/20/09
Closures will also be available in php, check this article http://codeutopia.net/blog/2009/02/20/closures-coming-in-php-53-and-thats-a-good-thing/ .
Lucian Lature on 2/22/09
Very well explained. Thanks!
Tyler on 2/22/09
Lucian: I know, I’m looking forward to them :). They should help remove the need for declaring functions just to be used with functions like preg_replace_callback() which is good, as that is one part of PHP I’ve never liked. One notable difference with closures in PHP is you have to explicitly declare all local variables that are to be available in the enclosed function. Unlike Javascript which inherits all local variables of all previous stack-frames.
mark story on 2/22/09
A clear, informative overview. Well done.
Drinkspiller on 2/25/09
Thanks for great explanation.
“So a closure is a stack-frame that doesn’t go away after a function is complete.” this definition is the best “Closure” definition I have ever seen.
jsonx on 9/9/09
Thank you so much for the great article! The last example is exactly what I was looking for. Big thanks for keeping me from tearing my hair out =)
Chrisco on 10/29/09
Excellent grasp of the material, thanks!
Berend de Boer on 1/15/10
Great overview, thanks
Sofox on 7/14/10
I think it would be more accurate to say right up front that our normal notion of a “stack” (as used to hold parameters and local variables) does not exist in languages like JavaScript (and Scheme, etc). Unlike Pascal, Ada, C, C++, Java, etc., JavaScript has only “heap” with garbage collection; all those “stack frames” to hold parameters and local variables are just more objects on the heap. When no more references to each exist, they individually get garbage collected. This means that there is no special “saving the stack frame” after the function has returned for closures…they all just get garbage collected like everything else when all references to it are deleted.
BTW, the only way I ever Grokked this was after watching (on iTunes U) the UC-Berkeley Comp Sci 61A class on Scheme. Except for the EARRRRLY Fortran days with no recursion on CDC supercomputers, I had not experienced a language that wasn’t fundamentally stack-oriented. The class video explained (with pictures) how the “stack frames” are instead “environments” that chain to each other (just like JavaScript objects chain via Prototypes). There is a global environment with the global vars, a new environment for each function (to hold params and local vars), and instead of a stack of frames on a hardware stack, it is a linked list of enviroments on the heap.
Did this make sense?
polyglot on 1/13/11
As a followup comment, it probably also requires explaining right up front that unlike the Pascal…Java languages (where functions are defined at COMPILE-TIME), JavaScript/Scheme/etc languages define functions at RUN-TIME. Because of this, there is always an environment (ala previous comment) that is active at the time of function creation/definition. It is like the call-stack that exists when the code defining the function is executed. [EXCEPT, of course that there is no stack. There is a great way to visualize how the stack is really a tree now, at… http://en.wikipedia.org/wiki/Spaghetti_stack].
This “current environment” chain is saved as a part of the function definition. In Java-like languages this makes no sense because there is no “current stack or environment” at compile time when the function was defined/compiled.
SO, when that function gets called, instead of “pushing” its params/local vars on top of THE stack, it “pushes” it on top of the environment stack that was saved with the function definition…and since it isnt a real(hardware) stack, but actually sitting in Heap, the function can refer to “local variables” of its “outer” function long after that outer function has returned.
polyglot on 1/13/11
nee mohama katla undi
raj on 8/3/11
in one line – bottom to top access is possible in javascript, but not the reverse.
Ramesh on 1/17/12
actually, that is not the one line to remember. Any language that has nested class/function/procedure definitions has bottom to top but not top to bottom access as you put it. E.G. Algol, Pascal, Ada, Java.
The real difference about JavaScript is that those “upper level” variables you access will still exist after the “upper level” functions have returned/exited! [None of those stack-based languages do that.]
polyglot on 1/17/12
When I try this code, it shows in firefox and chrome 1,2,3,4,5 and not just 5 as mentioned in the lexical scope section… I don’t understand it :-(
—-
anchor.addEventListener(‘click’, function(event) { alert(‘My number is ‘ + num); event.preventDefault(); }, false); }var numbers = [1, 2, 3, 4, 5];
for (var i in numbers) { var num = numbers[i]; var anchor = document.createElement(‘A’); anchor.setAttribute(‘href’, ‘#’); anchor.appendChild(document.createTextNode(num)); document.body.appendChild(anchor);
chabis on 3/10/12
Even after all these years (decade of so) of developing in Javascript I still come back to this subject of scope and closures ever so often as it does occasionally bite me in the proverbial.
Good article, well written and a nice reference to refer to when I do feel the need to look this subject over.
Quinton on 4/9/12
 For my understanding this modification should also do the trick in the last example and keep things more readable. It initialises a variable within the closure with the current value of num in the loop .
 anchor.addEventListener(‘click’, function(event) { var eventNumber = num;     alert(‘My number is ‘ + eventNumber);     event.preventDefault();   }, false);Alex on 4/27/12
 For my understanding this modification should also do the trick in the last example and keep things more readable. It initialises a variable within the closure with the current value of num in the loop .
 anchor.addEventListener(‘click’, function(event) { var eventNumber = num;     alert(‘My number is ‘ + eventNumber);     event.preventDefault();   }, false);Alex on 4/27/12
Thanks for clarifying lexical scoping, the simplest explanations are always the best. I am slowly learning javascript by going through the online book Eloquent Javascript and needed to see some more examples.
Pete on 8/16/12
For the sake of correctness on the article, I think you should take a look at http://stackoverflow.com/questions/14995018/does-this-example-prove-javascript-is-not-truly-statically-scoped in reference to the “More on Lexical Scoping” section.
Matt s. on 2/21/13