2

To the best of my understanding, the code

var a = new Array("a","b","c");
var out = "";
for(i in a)
  out += i+":"+a[i]+"\n";

should set out to

0:a
1:b
2:c

right?

Well, I have the following code snippet in a project of mine:

for(i in player.neededItems)
{
  debug(i+":");
  if(!player.hasItem(player.neededItems[i].type))
    itemsRemaining.push(player.neededItems[i]);
  debug(i+"<br />");
}
  • debug(x) is simply a function that appends x to the contents of a div with id "debug".
  • player.neededItems is an array of objects.
  • itemsRemaining is a previously empty array.
  • player.hasItem returns wether or not the player has an item.

Ok. So here's where it get's weird. In the for loop, 'i' is only used as an index to an array. It is not modified in any way. However, the output in "debug" is as follows:

0:3
1:3
2:3
3:3

Why is 'i' changing?! player.neededItems does not get modified in any of the functions or anything. I have no idea what is going on. But, when I switch

for(i in player.neededItems)

for

for(i = 0; i < player.neededItems.length; i++)

everything works.

So am I missing something regarding the functionality of 'for(i in a)' syntax? Or have I stumbled upon a bug in the javascript parser in webKit? Or (more likely,) am I going mad?

4
  • 4
    try var i, without the var keyword ahead of a variable I believe it is implicitly declared global. There might be some other i in your program that is interfering. Commented Aug 1, 2012 at 17:03
  • 2
    You sbould never iterate over an array using for-in. For its not convinient, but much worse its pretty slow performancewise. Commented Aug 1, 2012 at 17:08
  • 2
    Iterating over arrays with for-in also breaks if someone adds extra methods to the array prototype (as, for example, the Prototype library does) and it is not guaranteed to iterate over the keys in order. Use a numeric for loop for(var i=0; i<arr.length; i++) or an array iteration method (arr.forEach) instead. Commented Aug 1, 2012 at 17:11
  • 1
    Adding the 'var' seemed to work. Turns out player.hasItem uses i in a for loop as well, setting the 'global i' to the last in its enumeration. Since I never explicitly declared 'i' in a global scope, I assumed it was safe and that the 'var' was implied. I guess not, haha. Thanks everyone! Commented Aug 1, 2012 at 17:38

1 Answer 1

1
for(var i in player.neededItems)
{
  debug(i+":");
  if(!player.hasItem(player.neededItems[i].type))
    itemsRemaining.push(player.neededItems[i]);
  debug(i+"<br />");
}
Sign up to request clarification or add additional context in comments.

1 Comment

He added 'var' in the () of the for loop. That worked. What happened (as described by Hunter McMillen in the comments above) was that 'i' was being considered as the global instantiation of 'i' (which confused me, because I had never explicitly declared I globally...), and I used an undeclared 'i' in a loop in 'player.hasItem' as well, which resulted in 'i' always being the last index in a different array, which happened to be of length 3.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.