Fastest Loop in JavaScript
In this post, I wanted to test whether choosing the right loop can actually make your app faster.
Since array access time is O(1), they’re already efficient but which loop handles them best?
Now you might say: “It doesn’t even matter. Machines are fast enough.” True in most cases. But not everyone has a high-end device or blazing-fast network. Optimization still matters, especially at scale.
The Experiment
Here are the loop types we’re comparing:
- for
- for of
- for in
- forEach
- while
Test case: Loop through 1,000,000 numbers, and repeat that 1000 times for each loop type.
I ran the benchmark in two environments:
Each loop is measured with:
- Average time
- Median time
- Standard deviation
The Setup
Loop types are measured like this:
measureLoopType("for-of");
measureLoopType("for");
measureLoopType("for-in");
measureLoopType("forEach");
measureLoopType("while");
No external packages used. Just a simple getStats
function that returns averages, medians, and std dev:
const getStats = (totalDurations) => {
const averageDuration =
totalDurations.reduce((acc, curr) => acc + curr, 0) / totalDurations.length;
const sortedDurations = [...totalDurations].sort((a, b) => a - b);
const mid = Math.floor(sortedDurations.length / 2);
const median =
sortedDurations.length % 2 !== 0
? sortedDurations[mid]
: (sortedDurations[mid - 1] + sortedDurations[mid]) / 2;
const mean = averageDuration;
const squareDiffs = totalDurations.map((value) => (value - mean) ** 2);
const avgSquareDiff =
squareDiffs.reduce((acc, curr) => acc + curr, 0) / squareDiffs.length;
const standardDeviation = Math.sqrt(avgSquareDiff);
return {
averageDuration,
median,
standardDeviation,
};
};
Next, define the number array and tracking map:
const numbers = Array.from({ length: 1_000_000 }, (_, index) => index + 1);
const runs = 1000;
const totalDurations = new Map();
Benchmark logic:
const measureLoopType = (type) => {
for (let i = 0; i < runs; i++) {
const startTime = performance.now();
// loop goes here...
const endTime = performance.now();
const duration = endTime - startTime;
if (totalDurations.has(type)) {
totalDurations.get(type).push(duration);
} else {
totalDurations.set(type, [duration]);
}
}
};
Loop switch statement:
switch (type) {
case "for-of":
for (const number of numbers) {
// Operation
}
break;
case "for":
for (let i = 0; i < numbers.length; i++) {
// Operation
}
break;
// ... other loops
}
And finally, print the results:
let results = [];
totalDurations.forEach((value, key) => {
const stats = getStats(value);
results.push({
LoopType: key,
Average: `${stats.averageDuration.toFixed(4)} ms`,
Median: `${stats.median.toFixed(4)} ms`,
StdDev: `${stats.standardDeviation.toFixed(4)} ms`,
});
});
console.table(results);
Results
Bun
Bun gave me a surprise: forEach was the fastest loop.
Its average execution time was just 0.6244 ms
with a very low standard deviation, fast and consistent.
The for
and while
loops followed closely.
But for-in
was much slower, as expected.
In Bun, forEach is the winner. Unexpected, but real.
Node.js
In Node.js, the results were more predictable:
while
was the fastest with a median of0.3099 ms
for
was almost identicalforEach
was a bit slowerfor-in
was again the slowest
Also, while
had a small std dev of 0.1874 ms
, showing reliable performance across iterations.
GitHub: Fastest Loop in JS
The biggest surprise: in Bun, forEach was the fastest. Breaking the usual assumptions.
It shows how runtime environments can affect performance, even in simple constructs like loops.
On the server side, choosing the right loop isn’t just a nitpick. It can help you save compute and improve latency. Test in your environment, and don’t rely on assumptions.