Javascript closures illustration

Jack Slocum mentioned in a comment the problem comes from the creation of a global variable. When you create a local variable, you don't get the problematic behaviour. Thanks Jack for taking the time to correct me.

Intro

Here is the illustration of a bug that was present in version 0.1 of the yui slideshow. If you don't know what closures are, you should take a look at the Javascript closures for dummies which is really a great resource.

The problem

Here is a class that is plagued with the same problem as v0.1 of the yui slideshow:
var test = function(name)
{
        this.name = name;
}

test.prototype= {
        setInitial:  function( b )
        {
                name=this.name;
                if (b)
               {
                         this.callback = {
                         initial: function(){return name[0];}
                         }
                }
                else
                {
                        this.initial=name[0];
                }
        },
        getInitial:  function()
        {
                if (this.callback)
                        return this.callback.initial();
                else
                        return this.initial;
        }
}
An instance of this class is initialised with a name. On this instance, we can call the setInitial method which prepares everything so that getInitial can correctly return the first letter of the name. As you can see, there are two ways to set the initial: either directly to a member variable, or through an object callback. This reflects the code in the yui slideshow component: the next frame can either be present in the page (and as a member variable), or it has to be loaded remotely and can only be handled by a callback function once the XMLHTTP request has completed. To see what's wrong with this code, here is some code setting the stage:
r= new test('raphael');
c= new test('cathy');
r.setInitial(true);
c.setInitial();
This code creates 2 instances r and c, then call setInitial the callback way on r, and then calls setInitial the member variable way. Now, if you call r.getInitial you get.... 'c'. How comes? When you create the callback object, you have an anonymous function (closure) referencing the "name" variable (the "name" having the value "raphael"). However, by the time the function is run, the "name" variable is pointing to 'cathy' as the setInitial method is last run for the 'c' instance. This is equivalent to Example 5 of the Javascript closures for dummies page.

The solution

So, how can we correct the problem? As the problem is coming from closures, let's not reference the "name" variable from inside the anonymous function, and let's add a member variable arg to the callback object, which references the "name" variable:
setInitial:  function( b )
        {
                name=this.name;
                if (b)
                {
                         this.callback = {
                         initial: function(){return this.arg[0];},
                         arg: name
                         }
                }
                else
                {
                        this.initial=name[0];
                }
        }
With this code, r.getInitial() return "r" as expected.

See by yourself

I set up two page, one with the problem, the other with working code. Visit these pages and you'll see the results described.