How JavaScript’s closures surprised me

Well, it happened when I was making a web page on which the user could pick a number of time slots. The time slots would be configured using a calendar and a couple of time entry controls, and the user would add the time slot by clicking a button. The selected time slots would be stored as a JSON serialized array of time slots in an input element.

The selected time slots would be shown in a list on the page, each one with an X on the side which could be used to remove the appropriate time slot. The problem was, that it did not remove the appropriate time slot. But why?

It’s because of the way JavaScript’s closures are implemented!

You see, my code was something like this (using Crockford’s JSON library and the incredible jQuery):

What happened when I tried to remove the time slots? The most recently added time slot would get removed all the time, even though I clicked the first and the second etc.

At this point, I knew it was due to some JavaScript function closure stuff, because I could see that my click event handler would call removeTimeSlot with the id of the most recently added time slot all the time.

But why was this happening? I made all kind of changes to the snippet, moved the variables around, made several temporary variables, but the problem persisted!

Then I searched around, and I discovered two things that I did not know about JavaScript (and would not have expected):

  1. Variables reside in the function in which they are declared.
  2. Functions get the closure of their containing function.

I am a C# guy, and in C# I know that an anonymous delegate gets the closure that it needs and nothing more. I also know that variables declared inside the scope of for instance a for loop are local to that loop. So doing stuff like this would not cause any unexpected behaviour:

To put it another way, it means that my code was actually equivalent to this (notice how all my variabled are “declared” at the top of the function):

To circumvent this, I created an inline function which would deliver the DOM element with the link. Something like this:

– and from now on, to avoid unnecessary confusion, I will stop declaring my variables anywhere except the beginning of each function.

Lastly, I would like to give some shoutouts to the Mozilla folks for driving us all forward. Firefox 2 actually implements JavaScript 1.7, in which let was introduced as a keyword. let creates a new lexical scope and fixes one or more variables, which will then be promoted to a closure if necessary. Using let, my code would look like this:

– which is a lot simpler than the inline function version I ended up using. However, JavaScript 1.7 is not implemented by other browsers than Firefox 2 and Safari 3.x (according to Wikipedia) so it’s not really an option yet.