Javascript efficiency: 'for' vs 'forEach'

96,742

for

for loops are much more efficient. It is a looping construct specifically designed to iterate while a condition is true, at the same time offering a stepping mechanism (generally to increase the iterator). Example:

for (var i=0, n=arr.length; i < n; ++i ) {
   ...
}

This isn't to suggest that for-loops will always be more efficient, just that JS engines and browsers have optimized them to be so. Over the years there have been compromises as to which looping construct is more efficient (for, while, reduce, reverse-while, etc) -- different browsers and JS engines have their own implementations that offer different methodologies to produce the same results. As browsers further optimize to meet performance demands, theoretically [].forEach could be implemented in such a way that it's faster or comparable to a for.

Benefits:

  • efficient
  • early loop termination (honors break and continue)
  • condition control (i<n can be anything and not bound to an array's size)
  • variable scoping (var i leaves i available after the loop ends)

forEach

.forEach are methods that primarily iterate over arrays (also over other enumerable, such as Map and Set objects). They are newer and provide code that is subjectively easier to read. Example:

[].forEach((val, index)=>{
   ...
});

Benefits:

  • does not involve variable setup (iterates over each element of the array)
  • functions/arrow-functions scope the variable to the block
    In the example above, val would be a parameter of the newly created function. Thus, any variables called val before the loop, would hold their values after it ends.
  • subjectively more maintainable as it may be easier to identify what the code is doing -- it's iterating over an enumerable; whereas a for-loop could be used for any number of looping schemes

Performance

Performance is a tricky topic, which generally requires some experience when it comes to forethought or approach. In order to determine ahead of time (while developing) how much optimization may be required, a programmer must have a good idea of past experience with the problem case, as well as a good understanding of potential solutions.

Using jQuery in some cases may be too slow at times (an experienced developer may know that), whereas other times may be a non-issue, in which case the library's cross-browser compliance and ease of performing other functions (e.g., AJAX, event-handling) would be worth the development (and maintenance) time saved.

Another example is, if performance and optimization was everything, there would be no other code than machine or assembly. Obviously that isn't the case as there are many different high level and low level languages, each with their own tradeoffs. These tradeoffs include, but are not limited to specialization, development ease and speed, maintenance ease and speed, optimized code, error free code, etc.

Approach

If you don't have a good understanding if something will require optimized code, it's generally a good rule of thumb to write maintainable code first. From there, you can test and pinpoint what needs more attention when it's required.

That said, certain obvious optimizations should be part of general practice and not required any thought. For instance, consider the following loop:

for (var i=0; i < arr.length; ++i ){}

For each iteration of the loop, JavaScript is retrieving the arr.length, a key-lookup costing operations on each cycle. There is no reason why this shouldn't be:

for (var i=0, n=arr.length; i < n; ++i){}

This does the same thing, but only retrieves arr.length once, caching the variable and optimizing your code.

Share:
96,742
tonyrobbins
Author by

tonyrobbins

Trainee Web Dev. Currently studying Colt Steele's Web Dev Bootcamp.

Updated on December 12, 2020

Comments

  • tonyrobbins
    tonyrobbins over 3 years

    What is the current standard in 2017 in Javascript with for() loops vs a .forEach.

    I am currently working my way through Colt Steeles "Web Dev Bootcamp" on Udemy and he favours forEach over for in his teachings. I have, however, searched for various things during the exercises as part of the course work and I find more and more recommendations to use a for-loop rather than forEach. Most people seem to state the for loop is more efficient.

    Is this something that has changed since the course was written (circa 2015) or are their really pros and cons for each, which one will learn with more experience.

    Any advice would be greatly appreciated.

  • Admin
    Admin about 7 years
    Excellent, thorough, non-presumptuous answer, not bound to a single point in time, implementation, or micro-benchmark test.
  • tonyrobbins
    tonyrobbins about 7 years
    Perfect, that is exactly what i was looking for and gives a lot more depth than the video could. I really appreciate this, being new there is so much to learn and these are the things its easy to skip over by just favoring one over the other for no reason which could hinder you in the future. Many thanks!
  • Eric Grange
    Eric Grange over 5 years
    for-loop often have an advantage in terms of debugging: they're trivila to step into, breakpoint and inspect. With forEach() the extra callback level can complicate things a bit.
  • Felipe Buccioni
    Felipe Buccioni over 5 years
    Good answer, but the concept of Array.prototype.length is wrong isn't computed, here is an article that explains about it dmitripavlutin.com/the-magic-behind-array-length-property
  • vol7ron
    vol7ron over 5 years
    @FelipeBuccioni thank you, I actually was going to look into that as I think the engines now check if an array would be mutated to determine if the length is cached. Though, for legacy purposes I think the optimization engines were not as generous and length was a performance hit on each iteration. I’ll take a look at your article and incorporate that into the answer when I have time, or hopefully an outstanding member of the community will make an amendment as an edit for me :)
  • Solomon Ucko
    Solomon Ucko over 5 years
    What about for in?
  • vol7ron
    vol7ron over 5 years
    @SolomonUcko the question specifically asked about for and forEach. for..in could also be used to accomplish something similar, but it iterates over the properties of an object so it would require additional code. If seeking another alternative I would rather recommend the for..of that iterates over values.
  • Solomon Ucko
    Solomon Ucko over 5 years
    Oops, I think I confused the two.
  • user7393973
    user7393973 about 5 years
    I really enjoy the explanation in this answer and the phrase [...], if performance and optimization was everything, there would be no other code than machine or assembly.. I believe that with the let statement for declaring a block scope local variable, the second benefit of forEach is no longer an advantage over the for loop unless in an environment without support for let.
  • Microsis
    Microsis over 4 years
    Why ++i instead of i++?
  • vol7ron
    vol7ron over 4 years
    @Microsis there’s no reason here, it might have been microoptimization at the time, but that’s a browser/engine opt that’s inevitable to change. As they sit in the example, they are equivalent. Sometimes in my examples I try show a slightly different way of using the syntax to get newcomers thinking. All too often people see i++, but ++i captures attention and leads to a path of discovery that the final part of the for loop is an expression, which could be used for a number of operations and not just setting the loop increment.
  • vol7ron
    vol7ron over 4 years
    I’ll add that this answer could use some correction updates or addendums. For instance, many browsers these days internally optimize to bytecode, so repeated operations are performed once if certain conditions are met. I think if the array is untouched in the body of the loop, then it would only retrieve arr.length once. I’d welcome someone with more familiarity to weigh in.
  • SwiftNinjaPro
    SwiftNinjaPro over 4 years
    would overriding the forEach loop to run a for loop help performance? Array.prototype.forEach = function(callback){ for(let i = 0; i < this.length; i++){ callback(this[i], i, this); } };
  • vol7ron
    vol7ron over 4 years
    @SwiftNinjaPro I haven’t kept up with browser implementations, so I hope someone else could better answer you. I imagine under the hood it is already doing something similar, with some additional features. At this point, I couldn’t even tell you if replacing the initial function with an equivalent counterpart via prototype has any performance implications. It’s an interesting question and would be interesting to read the white paper on the code optimizer.
  • Dominic
    Dominic almost 4 years
    Another advantage of the for loop is iterating backwards without needing to reverse the data
  • Hit-or-miss
    Hit-or-miss over 3 years
    I don't think that this code for (var i=0, n=arr.length; i < n; ++i){} would be better than this one for (var i=0; i < arr.length; ++i){}. In fact, Js engine doesn't count the array elements. It just takes the number from the length property without counting the all array elements from scratch.
  • vol7ron
    vol7ron over 3 years
    @Hit-or-miss browsers used to perform a prop lookup (length) at each loop step. It isn’t a count, but it retrieved metadata in a costly fashion. With JS engines (and browsers) these days, this lookup is more-or-less avoided when the code is translated into bytecode. Internally it caches it and so we don’t have to worry about it as much anymore. Other optimizations like using arr[arr.length-1]= as opposed to arr.push() is now outdated, same thing for string concatenation. This is why micro-optimizations should be avoided over self-documenting code.
  • dhruv
    dhruv about 3 years
    Another key advantage of for-loop over forEach is that, forEach doesn't wait for asynchronous calls whereas you can use async await in for-loop in every iteration.
  • baptx
    baptx almost 3 years
    I usually use a for loop but I noticed that forEach has the advantage that it can work as one line of code, which is useful in a web console, for example to get rid of annoying elements: document.querySelectorAll(".someClassName").forEach(function‌​(el){el.remove()})
  • jave.web
    jave.web about 2 years
    Interesting microoptimization test 2022 Chrome: for...in is the slowest (like more than 100x slower), for...of is comparable to .forEach but still can be 2-3x slower than .forEach however classic for loop for(let i = 0; i < myArray.length; ++i) is even 10 times faster. And it all makes sense on the compilation level - for is just steping around at code place, forEach is doing similar, but is also jumping to the reference to the callback (most likely). All that being said, once you start to juggle objects around, all this doesnẗ matter. Objects are for now the biggest performance kil.
  • dmitry_stas
    dmitry_stas almost 2 years
    In JS there are no reasons use var i=0, n=arr.length; i < n instead var i=0; i < arr.length. In JS length of array is just property of Array object, and no additional costs are needed to get it (as opposed to, for example, PHP, where count() is function, and get count($arr) is much better one time instead each time in the loop)
  • Tomachi
    Tomachi almost 2 years
    Since the iterator is often statically specified as a constant i = 0, if the inner block is a pure function the compiler can safely perform loop unrolling and run it all concurrently. Probably so can forEach() if the function is pure and does not mind being run in random order.