What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use one loop for each level of a nested array. To change existing values, assign to the inner arrays or their elements; to produce a changed copy, return values from nested map() calls. The choice matters: forEach() runs callbacks but returns undefined, while map() builds a new array.
How do you visit every value in a nested array?
An outer loop visits each inner array as a value. Add an inner loop to visit the values inside that row. Keep the indices distinct so it is clear which nesting level each one refers to.
As an Amazon Associate I earn from qualifying purchases.
const grid = [
[1, 2],
[3, 4],
];
for (let rowIndex = 0; rowIndex < grid.length; rowIndex++) {
for (let columnIndex = 0; columnIndex < grid[rowIndex].length; columnIndex++) {
console.log(rowIndex, columnIndex, grid[rowIndex][columnIndex]);
}
}
Here, rowIndex selects an inner array and columnIndex selects a value within it. Use each row’s own length; nested arrays do not have to be rectangular.
How do you modify the existing nested array?
Assign to the value at the relevant row and column. This changes the existing nested arrays rather than creating a replacement.
#1 Best Overall
const grid = [
[1, 2],
[3, 4],
];
for (let rowIndex = 0; rowIndex < grid.length; rowIndex++) {
for (let columnIndex = 0; columnIndex < grid[rowIndex].length; columnIndex++) {
grid[rowIndex][columnIndex] *= 2;
}
}
// grid is [[2, 4], [6, 8]]
This is a straightforward use of numeric loops because the indices identify the elements to update. Nested for...of loops can also visit rows and values, but use an index-based loop when you need to assign by position.
When should you use forEach() or map()?
Choose based on the result you need. forEach() is for callback side effects; map() is for making a new array from callback results. Both can be nested, but their return behavior is different.
| Need | Approach | Effect |
|---|---|---|
| Change existing elements or perform another side effect | Nested forEach() |
Assignments in the callback can mutate existing rows. The method returns undefined. |
| Build a transformed nested array | Nested map() |
Each call returns a new array at its level; return the inner result from the outer callback. |
| Stop when a condition is met | for, for...of, or a short-circuiting method such as some() |
These approaches support stopping without throwing; forEach() does not support a normal break. |
| Remove values while preserving the original | filter() at the relevant level |
Build a new result rather than shifting elements during forward traversal. |
| Flatten one or more levels | flat() or, where suitable, flatMap() |
The output has a different nesting shape. |
Use nested forEach() for side effects
const grid = [[1, 2], [3, 4]];
grid.forEach((row) => {
row.forEach((value, columnIndex) => {
row[columnIndex] = value * 2;
});
});
The explicit assignments change the existing rows. The callback’s returned value is discarded, and the outer forEach() itself returns undefined. If you do not need callback return values, do not use map() and throw away its result.
Rank #2
forEach() skips sparse holes but visits an element explicitly assigned undefined. It also cannot be stopped with break; MDN’s forEach() reference notes that stopping it requires throwing an exception.
Use nested map() to return a transformed structure
const grid = [[1, 2], [3, 4]];
const doubled = grid.map((row) => row.map((value) => value * 2));
// grid: [[1, 2], [3, 4]]
// doubled: [[2, 4], [6, 8]]
The outer callback must return the inner map() result; otherwise, the outer result will contain the callback’s other return value, such as undefined. This example creates new arrays at both displayed levels. If the values are objects, nested map() alone does not deep-clone those objects. See MDN’s map() reference for the method’s return behavior.
Why doesn’t map() change my original array?
map() returns a new array containing the callback results; it does not replace the original array or mutate it just because the callback ran. Keep the result if you want the transformed version:
const doubled = grid.map((row) => row.map((value) => value * 2));
If you need to change the original values, assign to them explicitly in a loop or callback. If you only need side effects, use forEach() or a loop rather than calling map() and ignoring the returned array.
What happens if an array changes during iteration?
Array iterative methods such as forEach() and map() capture the array’s length when the method starts. They check indices up to that starting length, reading each value when its index is reached. Consequently:
- Appending beyond the starting length does not make the new element part of that method’s current traversal.
- Changing an unvisited index can change the value the callback later receives.
- Deleting an unvisited element means that index is skipped.
These rules apply at the level where the method is running. If an outer callback changes a row, the row’s own inner method has its own traversal. Concurrent changes can make control flow hard to follow, so avoid changing array lengths during traversal unless the behavior is intentional. MDN describes these rules in its Array reference.
Rank #4
for...of uses the array iterator, which checks the current length as it advances. Appending values while iterating can therefore cause those new values to be visited; if each pass appends another value, the loop may not terminate. The distinction is documented in MDN’s Array.prototype.values() reference.
How should you remove nested elements?
When you want to preserve the original, use filter() to build a new array at the level where values should be removed. For example, filtering rows and filtering values within each row are separate decisions; apply filter() at whichever level matches the data you want to exclude.
Free tools Windows power users keep installed
One-click scans. No signup required.
Avoid calling splice() on the array being traversed by a forward numeric loop unless you adjust for the shift. Removing an element shifts later indices left, so the next loop increment can skip the value that moved into the removed element’s position. For iteration guidance and loop alternatives, see MDN’s Loops and iteration guide.
Best Value
When should you flatten a nested array?
Flatten only when the new shape is actually useful. flat() returns a shallow new array and, by default, flattens one level; it leaves the original unchanged.
const nested = [1, [2, 3], [4, [5]]];
const oneLevel = nested.flat();
// oneLevel is [1, 2, 3, 4, [5]]
The remaining [5] stays nested because the default depth is one. Flattening discards the grouping at the levels it processes, so it is not a substitute for traversing or transforming while preserving rows. MDN documents the behavior in its flat() reference.
Quick Recap
What common nested-array mistakes should you avoid?
- Expecting
map()to mutate the original, or ignoring the new array it returns. - Expecting a value returned by a
forEach()callback to become an output array. - Using
forEach()when you need to stop early withbreak. - Using
for...into read array values. It enumerates property names and can include additional enumerable properties; use an array iteration method or a loop instead. - Confusing a sparse hole with an explicit
undefinedvalue when usingforEach(). - Assuming
forEach()andfor...ofbehave the same when elements are appended during iteration.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




