开发者

Binding jQuery click events via looping through hash grabs last element in hash?

I have a number of divs I am toggling on and off. I initially was manually binding the handlers(as per the code below), but decided to do some refactoring. However, a binding issue arose where the last key/value in the hash is the one always selected. In the example code, that would be the contact_data div. I think the problem is that the data is not being closed over, but I am not certain how to force this in JS.

v开发者_高级运维ar link_div = {
    "#about_toggle" : "#about_stuff",
    //more pairs
    "#contact_toggle" : "#contact_data"

 };
/*
 * Before refactoring:
  $("#about_toggle").click( function()
                          {
                              $("#about_stuff").toggle();
                          });
*/
//After
    for(var key in link_div)
    {
        $(key).click(function()
             {
                 alert(link_div[key]);
                 toggle_on_element(link_div[key]);
             });
    }


Actually the problem is, the data is being closed over. The anonymous function you pass in the event handler will close over your loop variable, therefore all event handlers reference the same variable. You need to invoke another function to avoid this:

for(var key in link_div)
{
    $(key).click(function(k)
         {
             return function() {
                alert(link_div[k]);
                toggle_on_element(link_div[key]);
             }
         }(key));
}


It's all about closures, which go back to the environment frame binding model of the language. Essentially key iterates through your loop and at the end, points to the last value in the map (which by the way, may not guarantee order, im not sure of the specific implementations). As such, the anonymous function (which is shared among all the elements, because it was created once, and therefore refers to one environment frame in memory) will for all elements, toggle link_div[key], but key, for all elements, has only one value.

You can solve this by either wrapping the anonymous function to make it unique for each binding (like jAndy did), or use a naming convention to make life a little easier:

$('.togglers').click(function(){ $('#'+$(this).attr('id')+'_stuff').toggle(); });
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜