3

I'm new with Prototype, but I use jQuery always. I have a site where I need to use jQuery as well as Prototype. I am having problems with the following code:

var x = [];
console.log(x);
for (var l in x)
{
console.log(l);
}

Running this code, x contains the following:


    each
    eachSlice
    all
    any
    collect
    detect
    findAll
    select
    grep
    include
    member
    inGroupsOf
    inject
    invoke
    max
    min
    partition
    pluck
    reject
    sortBy
    toArray
    entries
    zip
    size
    inspect
    find
    _reverse
    _each
    clear
    first
    last
    compact
    flatten
    without
    uniq
    intersect
    clone

Expected Result (without Prototype):

There are no child objects

Any reason why Prototype does this, and how to stop it?!

Thanks

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • [Never, ever use for-in-loops on arrays!](http://stackoverflow.com/q/500504/1048572) – Bergi Jul 16 '12 at 14:55
  • I know this isn't your question, but if you're using Prototype, don't forget about the many incredibly useful Enumerable methods, the most straightforward being [Enumerable.each()](http://api.prototypejs.org/language/Enumerable/prototype/each/). – dontGoPlastic Jul 16 '12 at 19:44

3 Answers3

7

You shouldn't use for...in for arrays, and this is exactly why.

for...in loops through all the properties of an object. This includes its properties (in this case, array indexes), and properties added to the prototype.

For arrays, just use a normal for loop.

var x = [];
console.log(x);
for(var i = 0, len = x.length; i<len; i++){
    console.log(i, x[i]);
}

Note: I do var i = 0, len = x.length because it only grabs the length from the array once, instead of on every iteration. It may be faster.

gen_Eric
  • 223,194
  • 41
  • 299
  • 337
  • It's just because I'm using a library called ui.selectmenu and the code is written like this, but I will modify the code :) – George Woodward Jul 16 '12 at 14:54
  • 1
    @GeorgeWoodward: Or yell at the library creators to fix it :-P – gen_Eric Jul 16 '12 at 14:55
  • He is asking how to get the properties of the object and not the properties of the entire inheritance chain.. so you would need a `x.hasOwnProperty(l)` – Waltzy Jul 16 '12 at 14:55
  • All posts here are saying not to use `for...in` for arrays. Could you explain what `for...in` is actually doing in this case? I.e. how does it reach the output it does? – corsiKa Jul 16 '12 at 14:57
  • 1
    @corsiKa it's showing all of the enumerable properties of `[]`, which on old, lame, browsers (and with Prototype.js) happens to include the enumerable properties of `Array.prototype`. – Alnitak Jul 16 '12 at 14:59
  • @Waltzy: `hasOwnProperty` is only needed when doing `for...in`, not when doing a normal `for`. – gen_Eric Jul 16 '12 at 15:04
  • 2
    @Alnitak Ah I see. So it's displaying the properties as opposed to the elements. Thanks for the explanation! – corsiKa Jul 16 '12 at 15:04
  • 1
    @corsiKa yes, that's right. To further complicate things, the elements of an array are _also_ properties! – Alnitak Jul 16 '12 at 15:05
  • I was mainly wanting to find out why it happens and now I know :) – George Woodward Jul 16 '12 at 15:09
5

You shouldn't use for..in on an array, you should use for( i=0; i<length; i++). But that aside:

for( l in x) {
    if( x.hasOwnProperty(l)) {
        // l is a property of your object
    }
}

This basically ignores the prototype chain for looping.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
0

When you use for ... in you're enumerating all of the (enumerable) properties of the array, and not just the numeric indexes.

Since Prototype.js adds lots of new functions to Array.prototype and fails to mark them as non-enumerable, those all appear in the list of properties too.

Alnitak
  • 334,560
  • 70
  • 407
  • 495