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.

JavaScriptbeginner
10 min read

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:

javascriptjavascript
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: date

This 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
ComponentValuePurpose
let i = 0Start at index 0Begin at the first element
i < fruits.lengthStop before lengthPrevent out-of-bounds access
i++Increment by 1Move 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

javascriptjavascript
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

javascriptjavascript
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

javascriptjavascript
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, 9

The for...of Loop

ES6 introduced for...of for iterating over the values of an iterable (arrays, strings, Maps, Sets):

javascriptjavascript
const colors = ["red", "green", "blue", "yellow"];
 
for (const color of colors) {
  console.log(color);
}
// red
// green
// blue
// yellow

for...of is cleaner when you only need the value and do not care about the index:

javascriptjavascript
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.8

Getting Both Index and Value with for...of

Use Array.entries() to get index-value pairs:

javascriptjavascript
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. Deploy

Classic for vs for...of Comparison

FeatureClassic forfor...of
Access to indexYes (i)Via .entries()
Access to valueVia array[i]Directly (item)
Skip elementsi += 2Not easily
Reverse iterationi--Not built in
Break/continueYesYes
Modify in placeYes (array[i] = x)Not directly
ReadabilityModerateHigh

Why for...in Is Wrong for Arrays

The for...in loop iterates over enumerable property names, not array values:

javascriptjavascript
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:

javascriptjavascript
// 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

javascriptjavascript
const stack = ["first", "second", "third", "fourth"];
 
for (let i = stack.length - 1; i >= 0; i--) {
  console.log(stack[i]);
}
// fourth, third, second, first

Reverse with for...of

javascriptjavascript
const items = [1, 2, 3, 4, 5];
 
for (const item of [...items].reverse()) {
  console.log(item);
}
// 5, 4, 3, 2, 1

Note: [...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

javascriptjavascript
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

javascriptjavascript
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

javascriptjavascript
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.97

Early Exit: Finding the First Match

Use break to stop as soon as you find what you need:

javascriptjavascript
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

javascriptjavascript
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:

javascriptjavascript
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

javascriptjavascript
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:

javascriptjavascript
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);
NeedUseWhy
Early exit with breakfor / for...ofArray 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 indexfor loopDirect index access
Accumulate a value.reduce() or forfor is often more readable for beginners
Modify in placefor loopMethods 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

Rune AI

Key Insights

  • Classic for loop for index access: use for (let i = 0; i < arr.length; i++) when you need the index for comparisons, modifications, or stepping
  • for...of for clean value iteration: use for (const item of array) when you only need the values
  • Never use for...in on arrays: it gives string keys, picks up inherited properties, and invites subtle bugs
  • Use break to 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
RunePowered by Rune AI

Frequently Asked Questions

What is the fastest way to loop through an array in JavaScript?

The classic `for` loop (`for (let i = 0; i < arr.length; i++)`) is consistently the fastest in benchmarks across [JavaScript engine](/tutorials/programming-languages/javascript/what-is-a-javascript-engine-a-complete-guide)s. Caching the length (`const len = arr.length`) can provide a small additional gain for extremely large arrays. However, for most applications, the performance difference between for loop types is negligible. Choose based on readability first; optimize only when profiling identifies a bottleneck.

Can I use for...of with objects?

No, plain objects are not iterable by default. `for...of` works with arrays, strings, Maps, Sets, and other iterables. To loop over object properties, use `for...in` or convert to entries first: `for (const [key, value] of Object.entries(obj))`. This gives you both the key and value in a `for...of` loop.

How do I loop through an array and remove elements?

Never remove elements while iterating forward, because it shifts indices and causes elements to be skipped. Instead, iterate backwards: `for (let i = arr.length - 1; i >= 0; i--)`. When iterating backwards, removing `arr[i]` shifts only elements after `i`, which you have already processed. Alternatively, use `.filter()` to create a new array without the unwanted elements.

What is the difference between forEach and a for loop?

The main differences are: `forEach` cannot be stopped early (no `break`), always iterates the entire array, and does not support `await` inside the callback for sequential async processing. A `for` loop supports `break`, `continue`, and `await`. Use `forEach` for simple side-effect operations where you always process every element. Use `for` or `for...of` when you need early exit or async control.

How do I get both the index and value in a for...of loop?

Use the `entries()` method: `for (const [index, value] of array.entries())`. This uses destructuring to give you both the index (as a number) and the value in each iteration, combining the readability of `for...of` with the index access of a classic for 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.