JavaScript – A Different Beast, Part-5: Closures

Using Closures – Examples

1. Closures as event handlers

Closures are extremely useful as event handlers. Say, you want to configure a button to do something. Naturally you will create a function and attach that as an event handler for that button. But, quite often, the code to be executed needs access to some data that is available only at the time of attaching it. In such cases, you can create a closure with the fixed values are bound variables and attach that as the event handler. See sample HTML page below, which has a textbox and a reset button. When the page opens, there is some value in the textbox (this normally would come from the web-server). User can change the value and then later reset it to the original value by clicking the reset button. The problem here is that when the reset button’s event handler executes, the original value is already gone. Look at how it is solved here using a closure.

//Example-1

<script type="text/javascript">// <![CDATA[
// <![<span class="hiddenSpellError" pre="">CDATA</span>[
// &lt;![&lt;span class=&quot;hiddenSpellError&quot; pre=&quot;&quot;&gt;CDATA&lt;/span&gt;[
// &lt;![&lt;span class=&quot;hiddenSpellError&quot; pre=&quot;&quot;&gt;CDATA&lt;/span&gt;[
// &lt;![&lt;span class=&quot;hiddenSpellError&quot; pre=&quot;&quot;&gt;CDATA&lt;/span&gt;[
        function load(){            var txt = document.getElementById('txt');            var initialValue = txt.value;            txt.onchange = function(){                var reset = document.getElementById('reset');                reset.onclick = function(){ //closure with initialValue bound                      txt.value = initialValue;                }           }//end of on-change        } //end of load
// ]]&gt;&lt;/script&gt;&lt;/pre&gt;
&lt;h3&gt;Example: Using closures for event handlers&lt;/h3&gt;


<pre> <input id="txt" type="text" value="25" /></pre>


 <button id="reset">Reset</button>Resets the textbox to the initial value(25)

2. Event handlers in a loop ( Good and bad closures )

Example HTML page below is a display board with 10 numeric keys and a text display. Hitting a number key should show the number in the display (textbox).

//Example-2 – Bad Closure&lt;script type=&quot;text/javascript&quot;&gt;// &lt;![&lt;span class=&quot;hiddenSpellError&quot; pre=&quot;&quot;&gt;CDATA&lt;/span&gt;[
       function load(){
          var buts = document.getElementsByTagName('button');
          for(i=0;i<10;i++){               buts[i].onclick = function(){ //bad closure                     document.getElementById('result').value += i;               };          }
// ]]&gt;&lt;/script&gt;&lt;/pre&gt;
&lt;h2&gt;Example: Bad Calc&lt;/h2&gt;
&lt;div id=&quot;calc&quot;&gt;
<input id="result" type="text" disabled="disabled" />
&lt;div&gt;&lt;button id=&quot;but0&quot;&gt;0&lt;/button&gt;
 &lt;button id=&quot;but1&quot;&gt;1&lt;/button&gt;
 &lt;button id=&quot;but2&quot;&gt;2&lt;/button&gt;
 &lt;button id=&quot;but3&quot;&gt;3&lt;/button&gt;
 &lt;button id=&quot;but4&quot;&gt;4&lt;/button&gt;
 &lt;button id=&quot;but5&quot;&gt;5&lt;/button&gt;
 &lt;button id=&quot;but6&quot;&gt;6&lt;/button&gt;
 &lt;button id=&quot;but7&quot;&gt;7&lt;/button&gt;
 &lt;button id=&quot;but8&quot;&gt;8&lt;/button&gt;
 &lt;button id=&quot;but9&quot;&gt;9&lt;/button&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre&gt;

The code here is wrong. Clicking on any button here gives you the same output – 10! The bug here is the accidental closure getting created. The code here is attaching a closure to the onclick handler, where the variable i is a bound variable. It is bound to the scope of load function where the value of variable i keeps changing till it reaches 10. All the ten closures created refers to the same scope and that scope is now having a value of 10 for i. Figure below shows the scope chain.

Accidental Closures
Accidental Closures

All the instances of the event handler functions are shown as f1, f2 upto f10. All these functions are created within the scope of function load and therefore share the scope and the variable i defined in it. Since the functions are then attached to the HTML DOM elements, 10 closures are formed causing the error.  Solution:Using yet another closure

//Example-2 – Good Closure&lt;script type=&quot;text/javascript&quot;&gt;// &lt;![&lt;span class=&quot;hiddenSpellError&quot; pre=&quot;&quot;&gt;CDATA&lt;/span&gt;[
         function makeHandler(digit){
               return function(){ //good closure, with digit bound in local scope
                      document.getElementById('result').value += digit;
               };
          }

          function load(){
                var buts = document.getElementsByTagName('button');
                for(i=0;i<10;i++){                        buts[i].onclick = makeHandler(i);                 }           }
// ]]&gt;&lt;/script&gt;&lt;/pre&gt;
&lt;h2&gt;Example: Good Calc&lt;/h2&gt;
&lt;div id=&quot;calc&quot;&gt;
<input id="result" type="text" disabled="disabled" />
&lt;div&gt;&lt;button id=&quot;but0&quot;&gt;0&lt;/button&gt;
 &lt;button id=&quot;but1&quot;&gt;1&lt;/button&gt;
 &lt;button id=&quot;but2&quot;&gt;2&lt;/button&gt;
 &lt;button id=&quot;but3&quot;&gt;3&lt;/button&gt;
 &lt;button id=&quot;but4&quot;&gt;4&lt;/button&gt;
 &lt;button id=&quot;but5&quot;&gt;5&lt;/button&gt;
 &lt;button id=&quot;but6&quot;&gt;6&lt;/button&gt;
 &lt;button id=&quot;but7&quot;&gt;7&lt;/button&gt;
 &lt;button id=&quot;but8&quot;&gt;8&lt;/button&gt;
 &lt;button id=&quot;but9&quot;&gt;9&lt;/button&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre&gt;

Here, the makehandler function is called in the loop to create a closure. Each call to makehandler creates a new instance of the scope object which has a variable digit bound to the argument passed (1 to 9). The event handler is still a closure, but with the variable bound to 10 different scope instances.

3. Scheduling

Scheduling is very similar to the first example, where a function has to be called after some time using the setTimeOut method in JavaScript. Closures are helpful in all callback scenarios.

Next topic: Objects without Classes

Further Reading:

  1. An in-depth explanation on closures – http://www.jibbering.com/faq/notes/closures/ 
  2. Some theory on First Class Functions – http://en.wikipedia.org/wiki/First-class_function

 

// ]]>

About Rahul Mohan

Technical researcher interested in model-driven development of enterprise business applications. Passionate about web technologies and a huge admirer of open-source especially in the Java landscape. When I am not doing any of the above you can find me with my camera (www.flickr.com/photos/rahulmohan/) or listening to music. (In fact, the title of the blog is inspired by Led Zeppelin's Physical Graffiti. )

Posted on May 15, 2011, in JavaScript, Tutorial and tagged , , , , , , , , . Bookmark the permalink. 4 Comments.

Leave a comment