JavaScript Loops.

Ernesto Jara Olveda
6 min readJan 9, 2020

In most programming languages, the majority of code execution time is spent within loops. Looping over a series of values is one of the most frequently used patterns in programming and as such is also one of the areas where efforts to improve performance must be focused. Understanding the performance impact of loops in JavaScript is especially important, as infinite or long-running loops severely impact the overall user experience.

Type of loops

ECMA-262, 3rd Edition, the specification that defines JavaScript’s basic syntax and behavior, defines four types of loops. The first is the standard for loop, which shares its syntax with other C-like languages:

for (var a = 0; a < someLength; a++) {   // yow code}

For Loop

The for loop tends to be the most commonly used JavaScript looping construct. There are four parts to the for loop:

  • initialization.
  • pretest condition.
  • post-execute.
  • loop body.

When a for loop is encountered, the initialization code is executed first, followed by the pretest condition. If the pretest condition evaluates to true, then the body of the loop is executed. After the body is executed, the post-execute code is run. The perceived encapsulation of the for loop makes it a favorite of developers.

While loop

while (a !== true) {

// yow code
}

A while loop is a simple pretest loop comprised of a

  • pretest condition
  • loop body

Code

Before the loop body is executed, the pretest condition is evaluated. If the condition evaluates to true, then the loop body is executed; otherwise, the loop body is skipped. Any for loop can also be written as a while loop and vice versa.

do-while loop

do {

// YOW CODE
} while (a !== true);

do-while loop is the only post-test loop available in JavaScript and is made up of two parts:

  • loop body
  • post-test condition

For in loop

for (const obj in objs) {
// yow code
}

The fourth and last loop is the for-in loop. This loop has a very special purpose: it enumerates the named properties of any object. The basic format is as follows:

Each time the loop is executed, the prop variable is filled with the name of another property (a string) that exists on the object until all properties have been returned. The returned properties are both those that exist on the object instance and those inherited through its prototype chain.

LOOP PERFORMANCE

A constant source of debate regarding loop performance is which loop to use. Of the four loop types provided by JavaScript, only one of them is significantly slower than the others: the for-in loop.

Since each iteration through the loop results in a property lookup either on the instance or on a prototype, the for-in loop has considerably more overhead per iteration and is therefore slower than the other loops. For the same number of loop iterations, a for-in loop can end up as much as seven times slower than the other loop types. For this reason, it’s recommended to avoid the for-in loop unless your intent is to iterate over an unknown number of object properties.

If loop type doesn’t contribute to loop performance, then what does? There are actually just two factors:

  • Work done per iteration
  • Number of iterations

By decreasing either or both of these, you can positively impact the overall performance of the loop.

Decreasing the work per iteration. It stands to reason that if a single pass through a loop takes a long time to execute, then multiple passes through the loop will take even longer. Limiting the number of expensive operations done in the loop body is a good way to speed up the entire loop.

A typical array-processing loop can be created using any of the three faster loop types.

// original loops
for (var i = 0; i < items.length; i++) {
process(items[i]);
}
var j = 0;
while (j<items.length) {
process(items[j++]);
}
do {
process(items[k++]);
} while (k < items.length);

In each of these loops, there are several operations happening each time the loop body is executed:

  • One property lookup (items.length) in the control condition
  • One comparison (i < items.length) in the control condition
  • One comparison to es whether the control condition evaluates to true (i < items.length == true)
  • One increment operation (i++)
  • One array lookup (items[i])
  • One function call (process(items[i]))

There’s a lot going on per iteration of these simple loops, even though there’s not much code. The speed at which the code will execute is largely determined by what process() does to each item, but even so, reducing the total number of operations per iteration can greatly improve the overall loop performance.

The first step in optimizing the amount of work in a loop is to minimize the number of object member and array item lookups.

hese take significantly longer to access in most browsers versus local variables or literal values. The previous examples do a property lookup for items.length each and every time through the loop. Doing so is wasteful, as this value won’t change during the execution of the loop and is therefore an unnecessary performance hit. You can improve the loop performance easily by doing the property lookup once, storing the value in a local variable, and then using that variable in the control condition:

Each of these rewritten loops makes a single property lookup for the array length prior to the loop executing. This allows the control condition to be comprised solely of local variables and therefore run much faster. Depending on the length of the array, you can save around 25% off the total loop execution time in most browsers (and up to 50% in Internet Explorer).

You can also increase the performance of loops by reversing their order. Frequently, the order in which array items are processed is irrelevant to the task, and so starting at the last item and processing toward the first item is an acceptable alternative. Reversing loop order is a common performance optimization in programming languages but generally isn’t very well understood. In JavaScript, reversing a loop does result in a small performance improvement for loops, provided that you eliminate extra operations as a result:

The loops in this example are reversed and combine the control condition with the decrement operation. Each control condition is now simply a comparison against zero. Control conditions are compared against the value true, and any nonzero number is automatically coerced to true, making zero the equivalent of false. Effectively, the control condition has been changed from two comparisons (is the iterator less than the total and is that equal to true?) to just a single comparison (is the value true?). Cutting down from two comparisons per iteration to one speeds up the loops even further. By reversing loops and minimizing property lookups, you can see execution times that are up to 50% – 60% faster than the original.

As a comparison to the originals, here are the operations being performed per iteration for these loops:

  • One comparison (i == true) in the control condition
  • One decrement operation (i – )
  • One array lookup (items[i])
  • One function call (process(items[i]))

The new loop code has two fewer operations per iteration, which can lead to increasing performance gains as the number of iterations increases.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response