Hi,

Both Ken and kangax have answered the practical question you posed,
but you're probably wondering why your code didn't work. :-)  It's
because in this line of code:

> item.onclick = function(){fc.selectArticle(id,headline);};

...you're assuming that 'id' and 'headline' become fixed at that point
in time, that you're burning their *values* into the closure function
(the onclick handler) at the point the function is defined.  That's
not how closures work.  They work by giving the function enduring
*access* to the things in scope where it's defined.  So for instance:

function chatter()
{
    var closures;
    var i;
    var msg;
    var closure;

    closures = [];
    for (i = 1; i <= 5; ++i)
    {
        msg = "This is message #" + i;
        closures.push(function() { alert(msg); });
    }

    for (i = 0; i < closures.length; ++i)
    {
        closure = closures[i];
        closure();
    }
}

This *doesn't* show five alerts saying "This is message #1", "This is
message #2", etc.  It shows five alerts saying "This is message #5",
because the functions access the 'msg' variable dynamically when
they're *called*, and by the time they're called, msg is "This is
message #5".  This is incredibly powerful, but can be a bit surprising
when you first look at it, especially when the closure lives on after
the function returns and you think that the local vars have
disappeared (they haven't, the closure preserves them).  So this works
the same way and has the same result:

function chatter()
{
    var closures;

    closures = createChatter();
    doChatter(closures);
}
function createChatter()
{
    var closures;
    var i;
    var msg;

    closures = [];
    for (i = 1; i <= 5; ++i)
    {
        msg = "This is message #" + i;
        closures.push(function() { alert(msg); });
    }

    return closures;
}
function doChatter(closures)
{
    var closures;
    var i;
    var closure;

    for (i = 0; i < closures.length; ++i)
    {
        closure = closures[i];
        closure();
    }
}

Note that the 'msg' variable lives even though createChatter() has
returned; each closure keeps a reference to the scope where it was
defined, and so that scope is preserved in memory even when it would
have been released if there were no closures involved.  (The other
local vars to createChatter() also live on; but nothing uses them, so
that's just wasted space.)

More on closures in my blog (which sadly I haven't had time to post to
lately):
http://blog.niftysnippets.org/2008/02/closures-are-not-complicated.html
http://blog.niftysnippets.org/2008/03/closures-by-example.html

This post may also be useful:
http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals.html
...as you have an implicit global variable 'i' in your code which you
almost certainly intended to be local to your "result" function. ;-)

Hope this helps,
--
T.J. Crowder
tj / crowder software / com

On May 15, 10:57 pm, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]>
wrote:
> Hi all,
> I am having trouble with my variable assignments always becoming the
> last variable inside my loop.
>
>                 var populateAvailableContent = Class.create(methodCall, {
>                         initialize: function($super, name, message) {
>                                 $super(name,'getAllContent','Loading...')
>                         },
>                         result: function(ret) {
>                                 var div = $('articles');
>                                 div.innerHTML = null;
>                                 var rowCount = ret.getRowCount();
>                                 for (i=0;i<rowCount;i++) {
>                                         var item = 
> document.createElement('div');
>                                         var id = ret.id[i]
>                                         var headline = ret.headline[i];
>                                         var html = headline + "<hr />";
>                                         item.id = "item";
>                                         item.onclick = 
> function(){fc.selectArticle(id,headline);};
>                                         item.innerHTML = html;
>                                         div.appendChild(item);
>                                 }
>                         }
>                 })
>
> In this scenario, id and headline are always becomes the last value in
> the loop and that is what is passed in the fc.selectArticle()
> function. I've tried a few different possible solutions I've found on
> the web, but none seemed to work. I decided to try and give the bind()
> function a go around but I can't seem to figure out how to use it in
> my situation.
>
> Any help would be greatly appreciated.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Spinoffs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-spinoffs?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to