开发者

How to exclude added to Array methods from processing in "for..in" loop? (javascript)

I've added some useful helpers to Array (such as toSource() for Opera). And now for..in ret开发者_JAVA技巧urns 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 ?


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.


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];
    }
};


There is another option now with ES5 support, it lets you define non-enumerable properties! It should be possible (though I haven't tested) to do something like this:

Object.defineProperty( Array.prototype, "myNewMethod", {
   value: function(){},
   writable: true,
   enumerable: false, /* this controls for..in visibility */
   configurable: true
});


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))
  {
    ...
  }
}


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.


Edit: corrected wrong typeof usage thanks to @Bergi 's comment

good point about performance when iterating over (very) sparse arrays - I'd suggest that perhaps using isNaN(parseInt()) in the loop lets you find array elements only:

for( var propertyName in myArray){
    if( !isNaN(parseInt(propertyName)) ){ /* probably array element */ }
}

I don't know what performs better of hasOwnProperty() and the above approach 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! :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜