Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is for-in slow in javascript?

Tags:

javascript

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 compared 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?

like image 906
patrick Avatar asked Nov 21 '12 08:11

patrick


2 Answers

The 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.

like image 81
T.J. Crowder Avatar answered Sep 24 '22 17:09

T.J. Crowder


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 complicated than an integer index variable.

In a typical for(var i = 0; i < arr.length; i++) loop, the two commands 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 commonly 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 complexity. 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! ;)

like image 29
AlexStack Avatar answered Sep 23 '22 17:09

AlexStack