views:

145

answers:

5

Hi.

I've added some useful helpers to Array (such as toSource() for Opera). And now for..in returns the functions with normal properties.

I'm using for..in now, because the code is easier to read with it. And it's a native functional of js, so must be faster.

But adding type checks in loop makes it easier to use classic for(;;).

Is there any methods to avoid for..in enumerate functions ?

Cross-browser work is not very necessary (must work in Opera), but speed is important.

Thank you.


Edit:
Is there any ability to avoid for..in enumerate functions or custom properties from any Object ?

+1  A: 

What you're describing is exactly why you use

for (var i=0; i<arr.length; i++) { ... }

instead of:

for (var item in arr) { ... }

because they are different.

If you don't want all the members that you'll get in the second form and just the indexed elements then use the first form.

cletus
Also read http://yuiblog.com/blog/2006/09/26/for-in-intrigue/
HappyCoder
Thank you. I have an Array, so for(;;) works fine. But Array is with holes (e.g. a[0]=some, a[100]=other and a[1..99] not used), so checks for element existence are needed. With for..in there is no this checks, but it's returns more then I need. I want to use fast and light construction to process elements. I'm new to js, so maybe it's better to use Object instead of Array for my task)
zxcat
HappyCoder, thanks for useful link!
zxcat
You are welcome.>I'm new to js, so maybe it's better to use Object instead of Array for my taskThe thing is, Array is Object. For-in walks the Object's properties. And a Function can be a property of an Object. Just don't create holes in Arrays and you'll be fine.I recommend you to learn Javascript the right way. This will help you a lot -- http://www.crockford.com/javascript/
HappyCoder
+4  A: 

You should never use for..in loops to iterate over array elements. for..in is designed for iterating over properties, and should only be used for that, for exactly the reason you've just described. Many libraries modify array, date, etc prototypes, so you should not rely on for..in iterating just the array elements. Use the for(;;) method, it's guaranteed to do what you want. And it's no faster than a for..in loop, because it's native to javascript as well.

For more info, read about it in the prototype.js library.

jvenema
Or use jQuery.eachhttp://jquery-howto.blogspot.com/2009/06/javascript-for-loop-vs-jquery-each.html
HappyCoder
Thank you for answer. One of the reasons, I tried to use for..in is that I don't like to write a lot of the same code.
zxcat
+2  A: 

As others stated, you should NOT use for..in to iterate over arrays. It is slower than using a for(;;).

You should also cache the length of the array if you are concerned with performance, as:

for (var i=0, len=arr.length; i<len; i++) 
{
  ... 
}

Use only for..in to iterate over properties of objects. To exclude the inherited properties, use the hasOwnProperty() method:

for (var prop in object)
{
  // Don't include properties inherited from the prototype chain
  if (object.hasOwnProperty(prop))
  {
    ...
  }
}
Pedro Simonetti
Thank you. Yes, I know about "caching", but this is another thing, I don't want to write, but want to have :) Don't want to write the same code in every loop. I know, I can use something like arr.MyFor(function() {..}), but don't know, how to write it and will it be better. About .hasOwnProperty - yes, I know, but check inside the loop is the thing I want to avoid.
zxcat
Hi zxcat,If you're really concerned with performance (I'm assuming that once you don't to make an extra check inside the loop), the best way to do is to write the whole loop by hand.Function calls are very expensive in JavaScript, compared to compiled languagens. Any kind of each() / myFor() function will perform MUCH SLOWER because you'll normally use 2 functions (the loop generator and the loop iterator).To avoid typing the same code every time, the best way is to use macros/templates/snippets or other features from your source code editor of choice.
Pedro Simonetti
+2  A: 

Yes, but it's JavaScript 1.7+ - only. Opera only has limited JavaScript 1.7 support, which includes very basic support of destructuring assignment so this won't work in Opera but it will work in Firefox.

This implementation allows safely using for [each](item in array):

Array.prototype.__iterator__ = function (flag) {
    var len = this.length, i = 0;

    for (; i < len; i++) {
     yield flag ? i : this[i];
    }
};
Eli Grey
Sick. What sets `flag`?
Crescent Fresh
Crescent: `flag` is true if the array was used in a `for..in` loop and false if it was used in a `for each..in` loop.
Eli Grey
A: 

Hi, good point about performance when iterating over (very) sparse arrays - I'd suggest that perhaps using for...in with a typeof check

for( var propertyName in myArray){
    if( typeof propertyName === 'number' ){ /* probably array element */ }
}

I don't know what performs better of hasOwnProperty() and typeof === 'number' though. You simply have to measure this with a very large array iterating it 10000 times or something like that. If you do some performance measurements, the results would be interesting so please share! :)

hallvors