171

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.

Flip
  • 6,233
  • 7
  • 46
  • 75
tonyrobbins
  • 1,733
  • 2
  • 9
  • 6
  • 21
    Why tie yourself to someone's subjective idea of a 2017 standard? Adopt a timeless standard, like writing clean, maintainable code, knowing that engineers are working hard to make the most commonly used constructs very efficient, and then optimizing for performance when you have a specific performance problem –  Mar 26 '17 at 17:22
  • 4
    A native `for` is tough to beat for pure speed. `forEach()` invokes a callback for each iteration; so, that obviously carries with it some overhead. – canon Mar 26 '17 at 17:23
  • 1
    being a developer I hardly use for or foreach, most of the work is done by map, filter or reduce methods. – A.T. Mar 26 '17 at 17:23
  • 21
    @A.T. as long as you're not one of those guys who uses `map` purely for the iteration and discards the new array it generates. I don't know how many people I've had to correct on that particular function choice on this site alone. – canon Mar 26 '17 at 17:25
  • 1
    @canon agreed, loop selection is important and one should keep output and residue of such methods in mind while choosing. I believe for readability plain "for loops" should be avoid. – A.T. Mar 26 '17 at 17:31
  • @Bergi link is down - can you explain this here briefly? – choz Jun 10 '19 at 19:54
  • 1
    @choz [new link](https://youtu.be/m9cTaYI95Zc?t=951) to the same talk – Bergi Jun 11 '19 at 12:15
  • @user1106925 Because `for (… of …)` is way more modern, clean, maintainable, and efficient than `Array.prototype.forEach`. – Константин Ван Dec 15 '22 at 10:54

1 Answers1

360

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.

Felipe Buccioni
  • 19,109
  • 2
  • 28
  • 28
vol7ron
  • 40,809
  • 21
  • 119
  • 172
  • 64
    Excellent, thorough, non-presumptuous answer, not bound to a single point in time, implementation, or micro-benchmark test. –  Mar 26 '17 at 18:15
  • 1
    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! – tonyrobbins Mar 26 '17 at 19:00
  • 4
    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. – Eric Grange Sep 17 '18 at 08:35
  • 1
    Good answer, but the concept of `Array.prototype.length` is wrong isn't computed, here is an article that explains about it https://dmitripavlutin.com/the-magic-behind-array-length-property/ – Felipe Buccioni Dec 11 '18 at 14:55
  • 1
    @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 :) – vol7ron Dec 11 '18 at 15:10
  • What about `for` `in`? – Solomon Ucko Dec 13 '18 at 19:51
  • @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. – vol7ron Dec 13 '18 at 21:58
  • Oops, I think I confused the two. – Solomon Ucko Dec 13 '18 at 22:18
  • 12
    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`. – user7393973 Apr 15 '19 at 08:55
  • Why `++i` instead of `i++`? – Microsis Aug 21 '19 at 04:11
  • 2
    @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 Aug 21 '19 at 16:40
  • 4
    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. – vol7ron Aug 21 '19 at 16:54
  • 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); } };` – SwiftNinjaPro Jan 09 '20 at 03:03
  • @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. – vol7ron Jan 09 '20 at 03:58
  • 7
    Another advantage of the for loop is iterating backwards without needing to reverse the data – Dominic Jul 24 '20 at 12:09
  • 2
    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. – Hit-or-miss Sep 14 '20 at 19:31
  • 1
    @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. – vol7ron Sep 14 '20 at 19:40
  • 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. – dhruv Mar 27 '21 at 06:44
  • 3
    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()})` – baptx Jul 23 '21 at 15:51
  • 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. – jave.web Mar 21 '22 at 22:25
  • 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) – dmitry_stas May 06 '22 at 12:27
  • 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. – Tomachi Jun 16 '22 at 17:39