最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jquery and javascript's closure - Stack Overflow

programmeradmin1浏览0评论

I am having the code below and javascript's closure together with anonymous functions are giving me a headache.

for (var i = 0, len = sites.length ; i < len ; i++)
{
  $("#thumb"+i).click(function() { $("#shader").show(); $("#thumbInfo"+i).show(); alert("#thumbInfo"+i); });
  $("#thumbInfo"+i+" .xbutton").click(function() { $("#shader").hide(); $("#thumbInfo"+i).hide(); });
}

Due to closure, i is always 5 (the sites array has 5 elements), so all the click handlers refer to the same id.

Any workaround?

I am having the code below and javascript's closure together with anonymous functions are giving me a headache.

for (var i = 0, len = sites.length ; i < len ; i++)
{
  $("#thumb"+i).click(function() { $("#shader").show(); $("#thumbInfo"+i).show(); alert("#thumbInfo"+i); });
  $("#thumbInfo"+i+" .xbutton").click(function() { $("#shader").hide(); $("#thumbInfo"+i).hide(); });
}

Due to closure, i is always 5 (the sites array has 5 elements), so all the click handlers refer to the same id.

Any workaround?

Share Improve this question asked May 1, 2011 at 3:59 George KastrinisGeorge Kastrinis 5,2025 gold badges32 silver badges48 bronze badges 1
  • IF you unroll the loop (replace it five times with i hardcoded) does it work? I have a feeling i is not the problem. – Abdullah Jibaly Commented May 1, 2011 at 4:09
Add a ment  | 

4 Answers 4

Reset to default 6

You could always loop with jQuery's each().

$.each(sites, function(i) {
  $("#thumb"+i).click(function() { $("#shader").show(); $("#thumbInfo"+i).show(); alert("#thumbInfo"+i); });
  $("#thumbInfo"+i+" .xbutton").click(function() { $("#shader").hide(); $("#thumbInfo"+i).hide(); });
});

use a closure in your for iteration:

for (var i = 0, len = sites.length ; i < len ; i++)
{
    (function(i) {
        $("#thumb"+i).click(function() {
            $("#shader").show(); 
            $("#thumbInfo"+i).show(); 
            alert("#thumbInfo"+i); 
        });
        $("#thumbInfo"+i+" .xbutton").click(function() { 
            $("#shader").hide(); 
            $("#thumbInfo"+i).hide(); 
        });
    }(i));
}

Place a function returning a function and parameterized by i outside the loop. JSLint will encourage you to do this anyway, and some might find it more readable to boot.

function make_fn1(i) {
    return function() { $("#shader").show(); $("#thumbInfo"+i).show(); };
}
function make_fn2(i) {
    return function() { $("#shader").hide(); $("#thumbInfo"+i).hide(); };
}
for (var i = 0; i < sites.length ; i++)
{
    $("#thumb"+i).click(make_fn1(i));
    $("#thumbInfo"+i+" .xbutton").click(make_fn2(i));
}

However, this could be cleaned up in other ways. For starters, as long as you're using jQuery, $("#shader, #thumbInfo"+i).show(); is more concise. Furthermore, in the current code the notion that the two functions either hide or show the same two elements is not factored out, so could be

function make_fn (i,showhide) {
    return function() { $("#shader, #thumbInfo"+i)[showhide]() };
}
for (var i = 0; i < sites.length ; i++)
{
    $("#thumb"+i).click(make_fn(i,'show'));
    $("#thumbInfo"+i+" .xbutton").click(make_fn(i,'hide'));
}
var len = sites.length ;
for (var i = 0; i < len ; i++)
    {
      $("#thumb"+i).click(function() { $("#shader").show(); $("#thumbInfo"+i).show(); alert("#thumbInfo"+i); });
      $("#thumbInfo"+i+" .xbutton").click(function() { $("#shader").hide(); $("#thumbInfo"+i).hide(); });
    }

you might have been assigning 5 to i;

发布评论

评论列表(0)

  1. 暂无评论