PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteiTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Use one loop for each array level. To change the existing nested arrays, assign to their elements; to produce a changed copy, return values from nested map() calls. Use forEach() for side effects, not to build a result. The right choice depends on whether you want to mutate, transform, stop early, or change the array’s shape.
How do you loop through an array of arrays?
An outer loop visits each inner array as a value. A second loop visits the elements inside that row. Keep the indices distinct: each belongs to a different nesting level.
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. Using each row’s own length also works when rows have different sizes. For an explanation of JavaScript loop forms, see MDN’s loops and iteration guide.
Free tools Windows power users keep installed
One-click scans. No signup required.
How do you change values in the existing nested array?
Assign to the desired element. A numeric loop is clear when the indices determine which values to update:
#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 changes the existing rows and their values without changing the arrays’ lengths. A nested forEach() can also make these assignments, but its callback return values do not become a result:
const grid = [[1, 2], [3, 4]];
grid.forEach((row) => {
row.forEach((value, columnIndex) => {
row[columnIndex] = value * 2;
});
});
forEach() returns undefined. The assignments above mutate the rows; the method itself does not create a transformed grid. It skips sparse holes but visits elements explicitly set to undefined. See MDN’s forEach() reference.
Rank #2
How do you create a transformed copy instead?
Return a value from each inner map(), then return that inner result from the outer callback. Each call creates an array at its own level:
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesconst 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 original array remains unchanged here. Because this example contains numbers, the new nested arrays contain transformed values. If the elements are objects, nested map() alone does not deep-clone those objects; references to them may still be shared. Use map() when you need its returned array, rather than calling it for side effects and discarding that result. See MDN’s map() reference.
Which approach should you choose?
| Goal | Approach | Effect |
|---|---|---|
| Change an existing value by index | Nested numeric for loops |
Assignments mutate the existing array; indices are explicit. |
| Perform an action for each visited value | Nested forEach() calls |
Useful for side effects; callback results are discarded and the method returns undefined. |
| Build a transformed nested structure | Nested map() calls |
Returns new arrays at the mapped levels; return the inner result from the outer callback. |
| Remove or keep selected elements | filter() at the relevant level |
Builds a filtered result rather than shifting elements during forward traversal. |
| Stop when a condition is met | for, for...of, or a short-circuiting method such as some() |
Supports early termination; forEach() does not support a normal break. |
| Flatten one nesting level | flat() |
Returns a shallow array and removes the selected level of nesting. |
What happens if an array changes while you iterate?
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, but read each value when its index is reached. As a result:
- Appending beyond the initial length does not make these methods visit the appended element.
- Changing an unvisited index can change the value the callback receives there.
- Deleting an unvisited element means that index is skipped.
These effects can make traversal difficult to reason about; avoid changing array contents or length during these callbacks unless the behavior is intentional. MDN describes this behavior in its Array reference.
Rank #4
for...of uses the array iterator, which reads the current length as it advances. Appending during the loop can therefore cause added elements to be visited; if each iteration appends another element, the loop may never finish. The iterator behavior is documented in MDN’s values() reference.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Removing elements safely
Removing the current element with splice() in a forward numeric loop shifts later elements left. The loop then advances, potentially skipping the element that shifted into the removed element’s position. If the original structure should be preserved, build a filtered result with filter() at the appropriate nesting level instead of splicing during traversal.
Best Value
Does flat() modify the nested array?
No. flat() returns a new shallow array and leaves the source unchanged. Its default depth is one:
const nested = [1, [2, 3], [4, [5]]];
const oneLevel = nested.flat();
// oneLevel is [1, 2, 3, 4, [5]]
The inner array containing 5 remains nested because the default operation flattens only one level. Flattening is a shape change, not a way to update values in place. See MDN’s flat() reference.
Quick Recap
Common mistakes to avoid
- Expecting
map()to change the original: it returns a new array. Store the result or use explicit assignments if you intend to mutate. - Returning a value from
forEach()and expecting an array: callback results are discarded, andforEach()returnsundefined. - Using
forEach()when you needbreak: it cannot be stopped through ordinary loop control. Use a loop or a short-circuiting method instead. - Using
for...infor array values: it enumerates property names and can include extra enumerable properties. Use an array loop,for...of, or an array method suited to the task. - Assuming a hole equals
undefined:forEach()skips an unassigned sparse slot, but visits a slot explicitly assignedundefined.
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.

