views:

275

answers:

4

So lets say I've added some prototype methods to the Array class:



Array.prototype.containsKey = function(obj) {
    for(var key in this)
        if (key == obj) return true;
    return false;
}

Array.prototype.containsValue = function(obj) {
    for(var key in this)
        if (this[key] == obj) return true;
    return false;
}

then I create an associative array and attempt to loop through it's keys:


var arr = new Array();
arr['One'] = 1;
arr['Two'] = 2;
arr['Three'] = 3;

for(var key in arr)
   alert(key);

this returns five items:
  -One
  -Two
  -Three
  -containsKey
  -containsValue

but I want (expect?) only three. Am I approaching this wrong? is there a way to "hide" the prototype methods? or should I be doing something differently?

+5  A: 

You can use JavaScript's hasOwnProperty method to achieve this in the loop, like this:

for(var key in arr) {
    if (arr.hasOwnProperty(key)) {
        ...
    }
}

Reference: This YUI blog article.

Kirtan
damn ppl... ur on the ball... that was quick, thanks!
Nick Franceschina
A: 

you could do this:

for(var key in arr)
{
   if (typeof(arr[key]) == "function")
      continue;
   alert(key);
}

But that's a shoddy workaround

nlaq
+2  A: 

Javascript doesn't support associative arrays the way you think they do. http://ajaxian.com/archives/javascript-associative-arrays-considered-harmful

for (var i in .. gets all of the properties of an object (an array is just another object) which is why you're seeing the other objects you've prototyped to it.

As the article suggests you should use an object:


var assoc = {'One' : 1, 'Two' : 2};
assoc['Three'] = 3;

for(var key in assoc)
   alert(key+' => '+assoc[key]);
rezzif
A: 

For high-performance iteration over JavaScript arrays, use either a for or while loop. Nicholas Zakas discusses the most-performant options for iterating over arrays in his Tech Talk Speed Up Your JavaScript.

Your best bet is probably something like this:

for (var i = collection.length - 1; i >= 0; i--) {
  if (obj == collection[i]) return true;
}

This approach will be peform best for a few reasons:

  • Only a single local variable is allocated
  • The collection's length property is only accessed once, at the initialization of the loop
  • Each iteration, a local is compared to a constant (i >= 0) instead of to another variable
Duncan Beevers
You can't iterate like that given the way he has used the array as he hasn't used numbers as the keys so collection[1] won't exist when he has called it collection['one']
rezzif