0

I am posting an answer to a question I could not find.

var imgs=[];
doge=new imgage_wrapper("50","10","10","doge1.png");
imgs.push(doge);


for(var i=0;i<imgs.length;i++)
{
    var test = imgs[i];
    setTimeout(function(){test.destructor()},1000);
}

This works. However,

for(var i=0;i<imgs.length;i++)
{
    setTimeout(function(){imgs[i].destructor()},1000);
}

Does not work. That is the answer.

Now, I am not sure I know WHY this is the answer. Can you illuminate me?

  • 1
    Actually none of them works, they both have the classic closure inside loops issue – adeneo Jul 24 '17 at 20:42
  • @adeneo The first one happens to work in this case because `imgs.length` is 1 and `test` ends up being the last value in `imgs`. – melpomene Jul 24 '17 at 20:43
  • @melpomene - it doesn't work when it doesn't do what it's supposed to. The difference is the first one doesn't throw an error, but it still doesn't work. – adeneo Jul 24 '17 at 20:46
  • @adeneo What do you mean by "it doesn't work"? – melpomene Jul 24 '17 at 20:47
  • The `test` variable is overwritten in each iteration, surely that isn't what the OP intended when he iterated over an array – adeneo Jul 24 '17 at 20:48

1 Answers1

0

Both examples have nested functions that use a variable (i) that is declared with var in a higher scope, causing a closure around i that persists into each call to that function. If you change the variable declaration from var i to let i (which gives i block level scope and ensures that a separate i value is created upon each loop iteration), the problem will be solved.

The first one happens to produce a result that you are OK with simply by accident. There is only one item in the array, so its length is 1 and therefore, your loop never gets the chance to iterate a second time and show you that both iterations use the same i value.

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71