Bug Tracker

Modify

Ticket #3776 (closed bug: invalid)

Opened 4 years ago

Last modified 4 years ago

$.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:
Blocking: Blocked by:

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

comment:1 Changed 4 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 4 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 4 years ago by mmikeyy

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

comment:4 Changed 4 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 4 years ago by dmethvin

  • Status changed from new to closed
  • Resolution set to invalid

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.

Please follow the  bug reporting guidlines and use  jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

View

Add a comment

Modify Ticket

Action
as closed
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.