I have read in several places that for-in loops are slower than looping over an array... Though I understand that moving forward in sizeof (type) blocks is practically effortless pared to whatever happens behind to the scenes to iterate over an object's keys, I am still curious, what the exact reason is that it's so slow...
Is it having to do a reverse hash function to get the key, and that process is what is slow?
I have read in several places that for-in loops are slower than looping over an array... Though I understand that moving forward in sizeof (type) blocks is practically effortless pared to whatever happens behind to the scenes to iterate over an object's keys, I am still curious, what the exact reason is that it's so slow...
Is it having to do a reverse hash function to get the key, and that process is what is slow?
Share Improve this question asked Nov 21, 2012 at 8:01 patrickpatrick 9,75213 gold badges65 silver badges126 bronze badges 2-
2
Yeah, I would guess that getting all the keys is a relative slow process pared to... not getting them ;)
for...in
has to lookup the keys first whereas with a normalfor
loop, you are providing the key through the loop variable. – Felix Kling Commented Nov 21, 2012 at 8:03 -
2
Here is a JSPerf test which shows that the run of
for...in
is almost the same asObject.keys()
(at least in Chrome): jsperf./for-in-vs-keys-vs-for. So, getting the keys and/or everything related to this is slower and providing the keys from the outside. But it also depends on the implementation, just as T.J. says. – Felix Kling Commented Nov 21, 2012 at 8:09
2 Answers
Reset to default 5The real answer to this in the case of any particular engine will likely depend on that engine's implementation. (As will the size of the difference, if any.)
However, there are invariants. For instance, consider:
var obj = {a: "alpha", b: "beta"};
var name;
for (name in obj) {
console.log(obj[name]);
}
var arr = ["alpha", "beta"];
var index;
for (index = 0; index < arr.length; ++index) {
console.log(arr[index]);
}
In the case of obj
, the engine has to use a mechanism to keep track of which properties you've already iterated over and which ones you haven't, as well as filtering out the non-enumerable properties. E.g., there's some kind of iterator object behind the scenes (and the way the spec is defined, that may well be a temporary array).
In the case of arr
, it doesn't; you're handling that in your code, in a very simple, efficient way.
The content of the block of each loop is the same: A property lookup on an object. (In the latter case, in theory, there's a number-to-string conversion as well.)
So I expect the only non-implementation-specific answer to this is: Additional overhead.
for..each
loops use iterators and generators.
Iterator is an object that has a next()
method. Generator is a factory function that contains yield()
expressions. Both constructs are more plicated than an integer index variable.
In a typical for(var i = 0; i < arr.length; i++)
loop, the two mands that execute in almost all iterations are i++
and i < arr
. This is arguably much faster than making a function call (next()
or yield()
).
Moreover, the loop initiation (var i = 0
) is also faster than creating the iterator object with next()
method or calling the generator to create the iterator. However, it highly depends on the implementation and the creators of Javascript engines do their best to accelerate such monly used language features.
I would say the difference is so marginal that I might want to spend my time optimizing other parts of the code. The choice of syntax should consider code readability and maintainability more than performance, when the performance gain is so small for adding plexity. Having said that, use the syntax that makes more sense to you and other developers who maintain your code after you get rich and famous! ;)