Bug Tracker

Opened 10 years ago

Closed 10 years ago

#3776 closed bug (invalid)

$.each iterator extremely inefficient with arrays with no values at lower index positions

Reported by: mmikeyy Owned by:
Priority: major Milestone: 1.3
Component: core Version: 1.2.6
Keywords: Cc:
Blocked by: Blocking:

Description

and it is not only inconvenient: it seems to be a bug.

The $.each function executes the function supplied as a 2nd parameter even for array positions that have never been filled (the 2nd argument passed to this function is then "undefined"). Why use the very efficient JQuery syntax if we end up having to write a more complex function to handle non-existing data?

Also, since the $.each function wastes time iterating over non-existing array elements, it can easily be HUNDREDS of times slower than the standard JS for(ind in array) construct, which is not affected by this problem.

On my computer with Firefox 3, iterating 100 times over a 2-element array with the highest index equal to 5000 takes... not even 1 ms with "for(ind in array)", and it takes 679 ms with $.each.

Change History (5)

comment:1 Changed 10 years ago by balazs.endre

Using a for..in loop on an array can cause problems if you (or others) extended Array.prototype, looping through the numeric indices is much safer!

$.each is not intended to be used on huge empty arrays, you can easily write a function based on $.each that skips unnecessary elements :) The native forEach method (if implemented) doesn't skip undefined properties either.

comment:2 Changed 10 years ago by mmikeyy

I just recently experienced this problem of properties added to the prototype popping up amongst array elements when the array is traversed the wrong way (with a for/in loop).

Filtering out the object properties to keep only array elements can be achieved as follows, I think:

for (ind in array) {

if (!isNaN(ind)) continue; array element processing...

}

Is this not incredibly more efficient than filtering out possibly hundreds or thousands of non-existent numeric indices?

The reason for all these unused array indices is that the data comes from a database and the unique record number is used as key value when it is stored in arrays. I may have just a few elements with a very high key value stored in an array.

Any advice on other / better ways of doing things is welcome.

In the meanwhile, I think I will write a variant of the $.each iterator to more efficiently process arrays.

comment:3 Changed 10 years ago by mmikeyy

Correction: the above code should read "if(isNaN(ind)) continue"...

comment:4 Changed 10 years ago by balazs.endre

  • isNaN won't help much as all the indices "exist" less then the length property (more precisely they are undefined)
  • for objects you could use the hasOwnProperty method
  • but here this is unnecessary, just use a loop like this:
    for(var i=0, l=array.length; i<l; i++){ 
      if(typeof array[i]=="undefined") continue;
      ...
    }
    
  • function calls also take some (very little) time, with a simple loop there isn't any

And since this is just a bug tracker such topics are better suited on the mailing list: http://groups.google.com/group/jquery-en/

comment:5 Changed 10 years ago by dmethvin

Resolution: invalid
Status: newclosed

The for/in is not a safe way to deal with an Array because of the issues that balazs.endre mentions. jQuery.each is also used for array-like objects such as the arguments list of a function. Using for/in would break that.

Note: See TracTickets for help on using tickets.