How to Loop Through Arrays using JS For Loops Guide
Learn every pattern for looping through JavaScript arrays with for loops. Covers index-based iteration, for...of, for...in, reverse looping, sparse arrays, and performance comparisons with array methods.
Arrays hold ordered collections of data, and for loops give you precise control over how you walk through them. Whether you need the index, the value, or both, there is a for loop pattern that fits. This guide covers every approach: the classic index-based for loop, the modern for...of loop, the for...in loop (and why you should avoid it for arrays), reverse iteration, early exit with break, selective processing with continue, and how for loops compare to built-in array methods like .forEach() and .map().
By the end, you will know exactly which loop pattern to reach for in any array-processing situation.
The Classic Index-Based For Loop
The standard for loop accesses array elements by index:
const fruits = ["apple", "banana", "cherry", "date"];
for (let i = 0; i < fruits.length; i++) {
console.log(`${i}: ${fruits[i]}`);
}
// 0: apple
// 1: banana
// 2: cherry
// 3: dateThis pattern gives you three things simultaneously:
- The current index (
i) - The current value (
fruits[i]) - Full control over start point, end point, and step size
| Component | Value | Purpose |
|---|---|---|
let i = 0 | Start at index 0 | Begin at the first element |
i < fruits.length | Stop before length | Prevent out-of-bounds access |
i++ | Increment by 1 | Move to the next element |
Use Strict Less Than
Always use i < array.length, not i <= array.length - 1. Both produce the same result, but the < pattern is the universal JavaScript convention and avoids confusing subtraction in the condition.
When You Need the Index
The classic for loop is the best choice when you need the index for any of these tasks:
Comparing Adjacent Elements
const temperatures = [72, 68, 75, 71, 80, 77];
for (let i = 1; i < temperatures.length; i++) {
const diff = temperatures[i] - temperatures[i - 1];
const direction = diff > 0 ? "up" : diff < 0 ? "down" : "same";
console.log(`Day ${i}: ${temperatures[i]} (${direction} ${Math.abs(diff)})`);
}
// Day 1: 68 (down 4)
// Day 2: 75 (up 7)
// Day 3: 71 (down 4)
// Day 4: 80 (up 9)
// Day 5: 77 (down 3)Modifying Elements in Place
const prices = [9.99, 14.5, 24.99, 7.0, 19.99];
for (let i = 0; i < prices.length; i++) {
prices[i] = Math.round(prices[i] * 100) / 100;
}
console.log(prices); // [9.99, 14.5, 24.99, 7, 19.99]Processing Every Nth Element
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Process every other element (even indices)
for (let i = 0; i < data.length; i += 2) {
console.log(data[i]);
}
// 1, 3, 5, 7, 9The for...of Loop
ES6 introduced for...of for iterating over the values of an iterable (arrays, strings, Maps, Sets):
const colors = ["red", "green", "blue", "yellow"];
for (const color of colors) {
console.log(color);
}
// red
// green
// blue
// yellowfor...of is cleaner when you only need the value and do not care about the index:
const scores = [85, 92, 78, 96, 88];
let total = 0;
for (const score of scores) {
total += score;
}
console.log(`Average: ${total / scores.length}`); // Average: 87.8Getting Both Index and Value with for...of
Use Array.entries() to get index-value pairs:
const tasks = ["Design", "Build", "Test", "Deploy"];
for (const [index, task] of tasks.entries()) {
console.log(`${index + 1}. ${task}`);
}
// 1. Design
// 2. Build
// 3. Test
// 4. DeployClassic for vs for...of Comparison
| Feature | Classic for | for...of |
|---|---|---|
| Access to index | Yes (i) | Via .entries() |
| Access to value | Via array[i] | Directly (item) |
| Skip elements | i += 2 | Not easily |
| Reverse iteration | i-- | Not built in |
| Break/continue | Yes | Yes |
| Modify in place | Yes (array[i] = x) | Not directly |
| Readability | Moderate | High |
Why for...in Is Wrong for Arrays
The for...in loop iterates over enumerable property names, not array values:
const letters = ["a", "b", "c"];
// for...in gives you string keys, not values
for (const key in letters) {
console.log(typeof key, key);
}
// string "0"
// string "1"
// string "2"This has three problems:
// Problem 1: Keys are strings, not numbers
const nums = [10, 20, 30];
for (const i in nums) {
console.log(nums[i] + 1); // Works, but i is "0", not 0
console.log(i + 1); // "01", "11", "21" (string concatenation!)
}
// Problem 2: Inherited properties appear
Array.prototype.customMethod = function () {};
const items = ["x", "y"];
for (const key in items) {
console.log(key); // "0", "1", "customMethod" (unexpected!)
}
delete Array.prototype.customMethod;
// Problem 3: Order is not guaranteed for all engines
// (Modern engines preserve order, but the spec doesn't require it)Never Use for...in on Arrays
Use for...in only for iterating over object properties. For arrays, use the classic for loop or for...of. Using for...in on arrays invites bugs from string keys, inherited properties, and potential ordering issues.
Reverse Array Iteration
Classic Reverse
const stack = ["first", "second", "third", "fourth"];
for (let i = stack.length - 1; i >= 0; i--) {
console.log(stack[i]);
}
// fourth, third, second, firstReverse with for...of
const items = [1, 2, 3, 4, 5];
for (const item of [...items].reverse()) {
console.log(item);
}
// 5, 4, 3, 2, 1Note: [...items].reverse() creates a reversed copy. It does not modify the original array. For large arrays, the classic reverse for loop is more memory efficient since it avoids creating a copy.
Filtering and Collecting with For Loops
Filtering into a New Array
const numbers = [3, 12, 7, 25, 8, 1, 19, 42];
const large = [];
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] >= 10) {
large.push(numbers[i]);
}
}
console.log(large); // [12, 25, 19, 42]Transforming into a New Array
const names = ["alice", "bob", "carol"];
const capitalized = [];
for (const name of names) {
capitalized.push(name[0].toUpperCase() + name.slice(1));
}
console.log(capitalized); // ["Alice", "Bob", "Carol"]Reducing to a Single Value
const cart = [
{ name: "Shirt", price: 29.99 },
{ name: "Pants", price: 49.99 },
{ name: "Socks", price: 9.99 },
];
let total = 0;
for (const item of cart) {
total += item.price;
}
console.log(`Total: $${total.toFixed(2)}`); // Total: $89.97Early Exit: Finding the First Match
Use break to stop as soon as you find what you need:
const users = [
{ id: 1, name: "Alice", active: false },
{ id: 2, name: "Bob", active: true },
{ id: 3, name: "Carol", active: true },
{ id: 4, name: "Dave", active: false },
];
let firstActive = null;
for (const user of users) {
if (user.active) {
firstActive = user;
break;
}
}
console.log(firstActive); // { id: 2, name: "Bob", active: true }Without break, the loop would process all four users even though the answer was at index 1. For large arrays, early exit significantly improves performance.
Skipping Elements with Continue
const data = [10, null, 25, undefined, 30, "", 45];
const valid = [];
for (const value of data) {
if (value == null || value === "") {
continue; // skip null, undefined, and empty strings
}
valid.push(value);
}
console.log(valid); // [10, 25, 30, 45]Nested Loops: Arrays of Arrays
Processing a 2D array (array of arrays) requires nested loops:
const grid = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
for (let row = 0; row < grid.length; row++) {
for (let col = 0; col < grid[row].length; col++) {
console.log(`[${row}][${col}] = ${grid[row][col]}`);
}
}
// [0][0] = 1, [0][1] = 2, [0][2] = 3, ...Flattening a 2D Array
const nested = [[1, 2], [3, 4, 5], [6]];
const flat = [];
for (const innerArray of nested) {
for (const value of innerArray) {
flat.push(value);
}
}
console.log(flat); // [1, 2, 3, 4, 5, 6]For Loop vs Array Methods
Modern JavaScript provides array methods that handle common iteration patterns. Here is when each approach works best:
const numbers = [1, 2, 3, 4, 5];
// For loop: full control, break/continue, index
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] === 3) break;
console.log(numbers[i]);
}
// .forEach(): no break, no return value
numbers.forEach((num, i) => console.log(i, num));
// .map(): returns new array
const doubled = numbers.map((num) => num * 2);
// .filter(): returns filtered array
const evens = numbers.filter((num) => num % 2 === 0);
// .find(): returns first match
const found = numbers.find((num) => num > 3);| Need | Use | Why |
|---|---|---|
Early exit with break | for / for...of | Array methods cannot break |
| Transform every element | .map() | Cleaner, returns new array |
| Filter elements | .filter() | Declarative, no manual pushing |
| Find first match | .find() | Built-in early exit |
| Need the index | for loop | Direct index access |
| Accumulate a value | .reduce() or for | for is often more readable for beginners |
| Modify in place | for loop | Methods return new arrays |
Start with For Loops, Then Learn Methods
Understanding for loops is essential before learning array methods. The methods are built on the same iteration concepts. Once you are comfortable with for loops, methods like .map(), .filter(), and .reduce() will feel like natural shortcuts.
Best Practices
Use for...of when you only need values. It is cleaner than the classic for loop and avoids off-by-one index errors. Switch to the classic for loop only when you need the index or need to skip/step.
Use break to stop early. If you are searching for a single item, exit the loop as soon as you find it. Processing the entire array wastes time on large datasets.
Avoid for...in on arrays. It iterates over enumerable property names (strings), not values. It also picks up inherited properties. Use for...of or the classic for loop instead.
Do not modify the array you are iterating. Adding or removing elements during iteration causes skipped or duplicated items. If you need to filter, build a new array. If you must modify in place, iterate backwards so that index shifts do not affect unvisited elements.
Extract the loop body into a function when it grows. If your loop body is more than 10-15 lines, pull it into a named function. This makes the loop readable at a glance and the body independently testable.
Next Steps
Learn [while loop](/tutorials/programming-languages/javascript/javascript-while-loop-explained-a-complete-guide)s for unknown iterations
When you do not know in advance how many times to loop, the while loop provides flexible iteration based on a dynamic condition.
Master array methods
Learn .map(), .filter(), .reduce(), .find(), and .some() to write declarative data transformations that replace many common for loop patterns.
Explore destructuring in loops
Combine for...of with object and array destructuring to extract exactly the properties you need from each element.
Work with async iteration
Learn for await...of to iterate over asynchronous data sources like streams and async generators.
Rune AI
Key Insights
- Classic
forloop for index access: usefor (let i = 0; i < arr.length; i++)when you need the index for comparisons, modifications, or stepping for...offor clean value iteration: usefor (const item of array)when you only need the values- Never use
for...inon arrays: it gives string keys, picks up inherited properties, and invites subtle bugs - Use
breakto exit early: stop processing as soon as you find what you need, especially in large arrays - Do not modify during forward iteration: build new arrays with
.push()or iterate backwards when removing elements
Frequently Asked Questions
What is the fastest way to loop through an array in JavaScript?
Can I use for...of with objects?
How do I loop through an array and remove elements?
What is the difference between forEach and a for loop?
How do I get both the index and value in a for...of loop?
Conclusion
Looping through arrays is one of the most common operations in JavaScript. The classic for loop gives you full control with index access, for...of provides cleaner syntax when you only need values, and both support break and continue for flow control. Avoid for...in on arrays because it iterates string keys and inherited properties. As you gain experience, you will reach for array methods like .map() and .filter() for common patterns, but a solid understanding of for loops is the foundation that makes those methods intuitive.
More in this topic
OffscreenCanvas API in JS for UI Performance
Master the OffscreenCanvas API to offload rendering from the main thread. Covers worker-based 2D and WebGL rendering, animation loops inside workers, bitmap transfer, double buffering, chart rendering pipelines, image processing, and performance measurement strategies.
Advanced Web Workers for High Performance JS
Master Web Workers for truly parallel JavaScript execution. Covers dedicated and shared workers, structured cloning, transferable objects, SharedArrayBuffer with Atomics, worker pools, task scheduling, Comlink RPC patterns, module workers, and performance profiling strategies.
JavaScript Macros and Abstract Code Generation
Master JavaScript code generation techniques for compile-time and runtime metaprogramming. Covers AST manipulation, Babel plugin authorship, tagged template literals as macros, code generation pipelines, source-to-source transformation, compile-time evaluation, and safe eval alternatives.