19

I'm implementing some code that is a natural fit for map. However, I have a significant amount of objects in a list that I'm going to iterate through, so my question is which is the best way to go abou this:

var stuff = $.map(listOfMyObjects, someFunction())

var stuff = listOfMyObjects.map(someFunction())

or just

var stuff = new Array(); 
for(var i = 0; i < listOfmyObjects.length; i++){
    stuff.push(someFunction(listOfMyObjects[i]));
}
dave
  • 12,406
  • 10
  • 42
  • 59
  • Your examples are not equivalent (nor makes the first code snippet sense). Do you mean to execute `someFunction` for each element in the list? Does it return a value and you want to replace the list entry with the return value? That is actually the idea of `map`. – Felix Kling Jul 01 '11 at 17:25

5 Answers5

12

here is a test case done in jsben.ch: http://jsben.ch/#/BQhED

it shows that a for-loop map is faster than a jquery map (at least in chrome).

EscapeNetscape
  • 2,892
  • 1
  • 33
  • 32
Socram
  • 165
  • 1
  • 6
  • 1
    I added the 3rd case described in the question as well, but your recommendation of the for loop approach still ranks first for me (chrome). – Adam Tuttle Nov 26 '11 at 19:03
  • Would be interesting to see how d3.js and underscore.js map methods compare to these. – amergin Jun 21 '14 at 01:47
10

The latter (for loop) is much faster. I remember seeing a benchmark somewhere but I can't seem to find the link.

If performance is really an issue then I would use the for loop. It doesn't really obscure the code that much.

tskuzzy
  • 35,812
  • 14
  • 73
  • 140
  • 8
    The for loop would probably be close-ish to the same performance unless he inlined the someFunction to the loop. map is essentially just doing the same thing with one extra function call, but the performance hit comes from calling the function every time, which populates the scope for each function. – Robert Jul 01 '11 at 17:25
7

First at all, true Objects don't have a native .map() method, neither a .length property. So we are either talking about Arrays or Array-like-objects (jQuery objects for instance).

However, there is not faster way to iterate than using a native for, while or do-while loop. All other functional operations do performan (guess what) a function for each iteration which costs.

jQuerys 's .each() will just performan a for-in loop when an object is passed to it. That is fairly the fastest way to loop over an object. You could just use a for-in yourself and you save the overhead call.

Another "good" way in terms of readabilty is to make usage of ES5 features like .keys() and .map(). For instance:

var myObj = {
    foo:  'bar',
    base:  'ball',
    answer: 42,
    illuminati: 23
};

Object.keys( myObj ).map(function( prop ) {
    console.log( myObj[ prop ] );
});

Which I think is a very good tradeof in terms of readabilty, convinience and performance. Of course you should use an ES5 abstraction library for old'ish browser.

But again, no way to beat native loops in terms of performance.

jAndy
  • 231,737
  • 57
  • 305
  • 359
  • Sorry, I mis-spoke. I meant to say objects in a list. Edited my question to make more sense. – dave Jul 01 '11 at 17:22
2

+1 for the "test it" answer by Emil :) That's always the right answer.

But yeah, native loops win, and you can do one better by caching the length so the .length reference isn't evaluated each iteration.

for(var i = 0, l = list.length; i < l; i++)

or avoid the extra var by doing it backwards

for(var i = list.length-1; i >= 0; i--)

And, if you can 'inline' the 'someFunction', that will be faster still. Basically, avoid function calls and references as much as you can. But that's only if you are really looking at fine detail. It's unlikely optimizations like this are going to matter much. Always test to find your bottlenecks.

InfinitiesLoop
  • 14,349
  • 3
  • 31
  • 34
1

Create a test cases with your html/javascript code at jsperf.

You will be able to see what works best, and how fast different browsers perform the loops.

I would put my money on the native JavaScript loop, but you never know.

Emil
  • 8,449
  • 3
  • 27
  • 44