Array methods vs loops
1. In short: what's going on
Array methods (map, filter, forEach, reduce, and so on) are abstractions over loops, implemented inside the JavaScript engine.
They're more convenient, shorter, and more readable,
but they carry extra overhead, which is why they can be slower than plain loops (for, for…of, while), especially on large arrays.
2. What happens "under the hood"
When you write:
arr.map(x => x * 2);the engine does roughly the following:
- Checks that
arris actually an array. - Creates a new array for the results.
- On every iteration:
- calls the callback function;
- passes it three arguments
(element, index, array); - stores the result in the new array.
- Returns the resulting array.
That's a bunch of steps that add overhead,
compared to a plain for loop, where you just run instructions with no wrappers or checks.
3. Why it's actually slower
| Reason | What happens |
|---|---|
| Callback function | A new function is called on every iteration -> extra call-stack frames |
| Creating a new array | map, filter, slice, concat create copies (extra memory) |
| Checks and context | The method runs through validations (length, holes, prototype, type) |
| Unoptimized closures | If the callback captures outer variables, that's even more overhead |
| Functional principles | These methods are "pure" and don't mutate data -> more allocations are needed |
| Loops are easier for the JIT compiler to optimize | The engine (V8, SpiderMonkey) optimizes a "bare" for faster |
4. A comparison example
const arr = Array.from({ length: 1_000_000 }, (_, i) => i);
// map
console.time('map');
const doubled1 = arr.map(x => x * 2);
console.timeEnd('map');
// for
console.time('for');
const doubled2 = new Array(arr.length);
for (let i = 0; i < arr.length; i++) {
doubled2[i] = arr[i] * 2;
}
console.timeEnd('for');On most engines the result looks roughly like this:
map: 30-60 ms
for: 10-20 msThe difference is small on small data,
but with millions of elements, for is 2-5 times faster.
5. Why this is especially noticeable in "hot" code paths
If a loop runs millions of times (rendering, sorting, data aggregation, parsing), callback overhead starts to "cost real time".
In such places:
- every callback call is a new call-stack frame;
- extra allocations mean more GC (garbage collector) work;
- extra arguments (
index,array) mean more objects in memory.
6. When it doesn't matter
For most business tasks (lists, filters, mapping up to 10k elements):
- the difference between
forandmapis fractions of a millisecond; - readability and clean code matter more.
That's why React/Vue code uses .map() for JSX, because it's declarative and clear:
{items.map(item => <Card key={item.id} {...item} />)}But if you have an array of millions of elements or a loop in a "hot path" (rendering, binary data processing, canvas, a parser), it's better to use:
for (let i = 0; i < n; i++) ...7. What's actually faster (in order)
| Loop | Speed | Notes |
|---|---|---|
for (let i = 0; i < n; i++) | The fastest | No checks, inline, predictable |
for...of | Fast, but uses an iterator | A little overhead |
while | About the same | Almost like for, depends on the engine |
forEach() | Slower (callback) | Doesn't return a new array |
map() | Slower, creates a new array | |
filter(), reduce() | Even slower | Allocations, extra operations |
8. How to speed up array methods
| Method | Optimization |
|---|---|
.map() | Use a pure arrow function inside it, with no outer closures |
.filter() | Don't chain .map().filter().reduce(), merge into one loop |
.reduce() | For complex operations, move the accumulation into a for |
.forEach() | Replace with for or for...of in "hot" code |
.concat() / spread ([...a, ...b]) | Replace with push.apply() or a loop for large arrays |
9. Brief summary
| Reason | Why it's slower |
|---|---|
| Callback functions | create extra calls and context |
| A new array | new memory is allocated |
| Validation and iteration | built-in checks and protocols |
| GC load | temporary objects are created |
| Loops are more primitive | easier for the JIT compiler to optimize |
Conclusion:
- For performance-critical tasks ->
for.- For clear, declarative code ->
map,filter,reduce.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.