1

In the following code sample i get a strange behavior

var data = ['xxx', 'yyy'];
for (var i in data)
{
    var a = i;
    var b = data[i];
}

The two first iterations works just fine. I get index "0" and "1" in i, but then it loops one extra time and now the i is "sum". Is this by design or what is this extra iteration used for? The result in my case is always empty and it messes up my code. Is there a way to not do his extra loop?

BR Andreas

Andreas
  • 6,958
  • 10
  • 38
  • 52

5 Answers5

6

It looks like you (or some other code you've included) have added extra properties onto the Array prototype. What you should be doing is checking to see whether the object you're iterating over actually has that property on itself, not on its prototype:

for (i in data) {
    if (data.hasOwnProperty(i)) {
        a = i;
        b = data[i];
    }
}

That said, you should never use for .. in on arrays. Use a regular for loop.

See here for more information: http://yuiblog.com/blog/2006/09/26/for-in-intrigue/

nickf
  • 537,072
  • 198
  • 649
  • 721
  • I think you've got it. I'll wager that there is another library adding Array.prototype.sum, making `for...in` iteration break. – cwallenpoole Aug 09 '11 at 08:10
  • From Wikipedia on this topic: "Iterates through all used indices of array including all user-defined properties of array object if any. Thus it may be better to use a traditional for loop with a numeric index when iterating over arrays." – hayesgm Aug 09 '11 at 08:10
5

You are looping through an Array, not through an Object. For arrays it's better to use:

for (var i=0; i<data.length; i=i+1){
  /* ... */
}

In your loop every property of the Array object is taken into account. That makes the for ... in loop for array less predictable. In your case it looks like sum is a property (method) that's added to Array.prototype elsewhere in your code.

There are more ways to loop through arrays. See for example this SO-question, or this one

Just for fun, a more esoteric way to loop an array:

Array.prototype.loop = function(fn){
  var t = this;
  return (function loop(fn,i){
   return i ? loop(fn,i-1).concat(fn(t[i-1])) : [];
  }(fn,t.length));
}
//e.g.
//add 1 to every value
var a = [1,2,3,4,5].loop(function(val){return val+1;});
alert(a); //=> [2,3,4,5,6]
//show every value in console
var b = [1,2,3,4,5].loop(function(val){return console.log(val), val;});
Community
  • 1
  • 1
KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • Iterating through `for...in` while not common is still a valid way to iterate through an array. – cwallenpoole Aug 09 '11 at 08:07
  • You're correct by the specification. It runs without a hitch in Firefox anyhow. – hayesgm Aug 09 '11 at 08:08
  • +1 to offset the -1... Usage of `for in` on arrays should be frowned upon, and so this is good advice. It doesn't *really* answer the question though, about why the `sum` variable is showing up. – nickf Aug 09 '11 at 08:12
  • @cwallenpole: I rephrased my answer. @nickf: edited the answer to give a possible explanation for `i` ending up as `sum`. – KooiInc Aug 09 '11 at 08:19
  • @Kooilnc I saw. I got rid of the -1. – cwallenpoole Aug 09 '11 at 08:25
2

Here's a way to safely iterate.

var data = ['xxx', 'yyy'];
for (var i = 0; i < data.length; i++)
{
    var a = i;
    var b = data[i];
}

What you are getting is an method coming from extending the Array object, I guess you are using some library where is something like Array.prototype.sum = function () {...};

Bojan Bjelic
  • 3,522
  • 1
  • 17
  • 18
1

Perhaps setting data like this would work better: var data = {0:'xxx', 1:'yyy'};

Calum
  • 5,308
  • 1
  • 22
  • 27
1

First of all data is an object. Try to add console.log(a); and console.log(b); inside your loop and you'll see.

silex
  • 4,312
  • 4
  • 22
  • 27