0

Let's say I have these two Object, one array and the other one an associative object.

var peopleObj = {
    1 : 'Joe',
    3 : 'Sam',
    8 : 'Eve'
};

var peopleArr = [
    { id: 1, name: 'Joe'},
    { id: 3, name: 'Sam'},
    { id: 8, name: 'Eve'}
];

Is there a really big overhead when finding an element (by id) with forEach compared to direct associative key ?

peopleObj['3'].name = 'New name';

peopleArr.forEach(function(human) {
    if (human.id == 3) {
        human.name = 'New name';
    }
});
Unitech
  • 5,781
  • 5
  • 40
  • 47
  • 1
    well, did you measure it? (also, does it even matter?) – The Paramagnetic Croissant Aug 09 '14 at 16:48
  • 2
    Yes, of course there is. (Btw, you shouldn't use `forEach`, you can't even `break` from that) – Bergi Aug 09 '14 at 16:48
  • 2
    All performance questions of interest should be measured with a representative data set. A tool like jsperf can help you do this. – jfriend00 Aug 09 '14 at 16:51
  • 1
    @Bergi - seriously, you think that's a dup. It isn't even really the same question and there's no decent answer. How is anyone's interest served by marking it a dup of that one? – jfriend00 Aug 09 '14 at 16:54
  • Here ask about performance difference because in the other post no one speak about perf, it's not a dup. – Unitech Aug 09 '14 at 16:57

1 Answers1

4

You'd have to define "really big," and you'd have to test it with your representative data, but the short answer is yes, it's more overhead to use forEach than direct property access, for a couple of reasons:

  1. Modern JavaScript engines are pretty smart about objects and can optimize direct property access quite well.

  2. To use forEach, you have to make function calls. Function calls are extremely cheap, but they aren't free.

  3. In the course of finding the element in the array, you'll be doing various direct property accesses (human.id), so right there you're doing the same work you'd've done with direct access, but you're doing it over and over again.

Now, not all objects are equal in terms of property access time. In particular, with a modern engine like V8, if you do something to the object that makes the engine throw away its optimizations and fall back on "dictionary mode" (treating the object like a hash table, instead of doing smarter things), property access on that object will be a lot slower than on one where the optimizations remain in place. One such operation is delete, which causes V8 to put the object in "dictionary mode." Example on jsperf (Firefox's engine, SpiderMonkey, bizarrely shows an improvement with the object delete was used on; perhaps it's so fast it's a measurement error, but I ran it several times with consistent results...)

So in theory, if you had a small number of entries in your array, and you built up the array in a way that let the engine optimize it as a true array behind-the-scenes, and the object you would have used instead would have been in "dictionary mode," maybe you might find a use case where forEach was faster. It doesn't seem likely, but it's remotely possible.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Ok so I will not transpose an array to an associative kind of hash map, if the difference is not that big. Thanks for your answer. – Unitech Aug 09 '14 at 16:59
  • 1
    @tknew: Well, `forEach` is by its nature going to be O(n), right? But property lookups are implementation-dependent. For an object you don't modify, V8 can do a property lookup on an object with 30 properties just as fast as one with one property, because it generates true classes. Whereas in dictionary mode, it's probably (I haven't looked at the source) using a binary tree or similar. – T.J. Crowder Aug 09 '14 at 16:59
  • @tknew: I don't recall saying the difference wasn't that big. Theory says it'll be quite a bit slower; that doesn't mean the decrease in speed will be a factor in your app. – T.J. Crowder Aug 09 '14 at 17:00