-
My name is Brad Harris, and I currently reside in the Abq, New Mexico area. I'm a web-developer, specializing in front-end development. PHP is my weapon of choice for the server side, but my creative side thrives on Javascript and CSS.
- Hoping for a snow day 2010/01/19
- Wrote a new post on "Getting keycode values in Javascript" - http://bit.ly/PIcup 2009/09/16
-
My Recent Ramblings
Categories
Archives
- September 2009 (1)
- January 2009 (3)
- December 2008 (1)
- September 2008 (2)
- August 2008 (2)
- July 2008 (3)
- April 2008 (2)
- March 2008 (2)
- February 2008 (1)
- January 2008 (1)
- November 2007 (1)
- October 2007 (1)
- September 2007 (3)
- August 2007 (1)
- June 2007 (1)
- May 2007 (2)
- April 2007 (1)
- March 2007 (2)
- February 2007 (3)
- January 2007 (1)
Scoping Javascript closures in loops
It must have been something I ate, cause this is like the third post in 2 days I think! This is a quick one, but super handy to know if you don’t already. There is semi-common problem I run into, and it has to do with scoping of closures inside of loops. Lets get straight to the code so its easier to understand what I’m talking about:
<html> <script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/utilities/utilities.js" ></script> <script type="text/javascript"> var values = [0,1,2,3,4,5,6,7,8,9]; for(var idx in values) { //First Test - will have incorrent scoping YAHOO.util.Event.addListener(window, 'load', function() { YAHOO.util.Dom.get('wrong-scope').innerHTML += ' '+values[idx]+' '; }); //Second Test - scoping will be correct YAHOO.util.Event.addListener(window, 'load', function(scopedValue) { return function() { YAHOO.util.Dom.get('right-scope').innerHTML += ' '+scopedValue+' '; } }(values[idx])); } </script> <body> <div id="wrong-scope"> <h1>Wrong Scope</h1> </div> <div id="right-scope"> <h1>Right Scope</h1> </div> </body> </html>In this example, there is a simple array of ordered values, and then a loop over those values. For each iteration of the loop, there is an onload listener added that will dump that value into a div. You’ll see the first loop always dumps 9, because the scoping is wrong when the closure executes, and the last time through the loop sets the scope of values[idx].
The second section does some unique handy-work to correct the scoping. A listener is added like before, but the closure is created in a specific fashion in order to get the scope to be the way we want at runtime. For the closure in the second section, we create a function, and immediately execute that function, passing in a parameter that is the current value in our array of numbers. That function runs, and returns another function that does the appending to the div of the value. This second, inner-function is what will execute on page load. Because of the outer-function we immediately called, the variable passed into it, the current value from our array, will be available, and properly scoped for our inner-function.
This is a handy trick when you have a situation where you are looping over a collection, and are providing some type of callback/closure for each entry, but need some proper scoping.