cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

Iterating arrays & array-likes

Choose the right loop for arrays, use keys, values and entries, convert array-likes with Array.from, and work safely with arguments and NodeList objects.

By the end, you can
  • 01
    Pick the right loopCompare for, for...of, and forEach when skipping, stopping, and reading indexes.
  • 02
    Use iterator helpersReach for keys(), values(), and entries() when you need positions, values, or both.
  • 03
    Handle array-likesConvert or borrow methods for arguments, strings, plain array-like objects, and browser NodeLists.

Choose the right way to walk a list

Arrays are ordered lists, but not every “walk through the list” job is the same. Sometimes you need the index. Sometimes you need to stop as soon as you find a problem. Sometimes you want to do one side effect for every item and never produce a new array. This lesson helps you choose the right tool and recognize things that look array-ish but are not real arrays.

The curriculum summary says it neatly: choose the right loop, and turn array-likes into real arrays. We will connect what you already know from Loops: while & for, for…of & for…in, Default & rest parameters, and Symbols. The formal iteration protocols come later; here we use the pieces you can apply today.

Working definition

Iterating an array means visiting its items in a predictable order. Array-like means “numbered slots plus a length,” but not necessarily array methods such as map or filter.

Real-life analogyThree ways to walk the lockers

If you walk a row of lockers yourself, you can count by twos, walk backward, or stop at locker 12. A tour guide is less fiddly: they simply hand you each item in order, and you can still say “stop.” A delivery service has a route card and visits every valid house; you can skip a package, but you cannot end the whole route from inside one delivery.

In real life: Walking the lockers yourself with a counter
In JavaScript: A for loop: full control over index, direction, skips, and stops
In real life: A tour guide hands you the next locker’s contents
In JavaScript: A for...of loop: values in order, with break still available
In real life: A delivery service visits every listed house
In JavaScript: forEach: a callback for each existing item, with no emergency stop button

Where the analogy stops: Real lockers are always physically present. JavaScript arrays can have holes: missing indexes that some tools visit as undefined and some tools skip.

Keep that mental model in mind as we compare the same task with three loops, then use iterator helpers, convert array-likes, borrow array methods carefully, and inspect real browser NodeLists.

for vs for…of vs forEach

STEP THROUGH

Our task is deliberately small: sum scores until a negative number appears, skipping zeroes. The data is [3, 0, 4, -2, 5]. A correct “until negative” version returns 7, because the 5 after -2 should never be counted.

Sum until a negative number
Step 0 of 11Ready
Your turn: follow the blue line

Same data, three loop styles. Predict whether the 5 after -2 is counted, then step through the real recorded run.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
let total = 0;for (let index = 0; index < scores.length; index += 1) {  const score = scores[index];  if (score === 0) continue;  if (score < 0) break;  total += score;}console.log(total);
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
Choose the loop style. Does the 5 after -2 get counted?

for and for...of can use break; forEach can only return from the current callback.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

The lesson is not that one loop is always better. It is that each loop makes a different promise:

  • for gives you the counter. Use it when the index is the main story, you need to move in a custom pattern, or you need full control.
  • for...of gives you values. Use it when you want clear value-by-value code and may still need break or continue.
  • forEach calls a callback for each existing item. Use it for side effects you truly want to run for every item; do not use it when you need early exit.
Comparing array iteration tools
ToolCan break?Index by default?HolesBest for
forYesYesVisits every numeric index; reading a hole gives undefinedFull control: start, stop, skip, go backward, change step size
for...ofYesNo, unless you use entries()Visits holes as undefinedReadable value-by-value loops that may stop early
forEachNoSecond callback parameterSkips holesDo the same side effect for every existing item
for...inYesGives property keys as stringsSkips holes but includes enumerable custom keysObjects, not arrays

Notice the fourth row: for...in is included because it is easy to confuse with for...of. On arrays it walks enumerable property keys as strings, including custom keys. Keep it for ordinary object properties; for arrays, choose one of the first three.

keys, values & entries

STEP THROUGH

Arrays have three small iterator helpers. keys() produces indexes, values() produces values, and entries() produces pairs: [index, value]. They do not produce arrays immediately; they produce iterator objects. If you want to see all results at once, convert them with spread syntax or Array.from.

Indexes, values, or pairs?
Step 0 of 9Ready
Your turn: follow the blue line

Step through the three iterator helpers: keys for indexes, values for items, entries for both.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
console.log([...queue.keys()].join(","));console.log([...queue.values()].join("|"));for (const [index, name] of queue.entries()) {  console.log(index + ":" + name);}
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

You already saw entries() with destructuring in the for…of lesson. The pattern is worth keeping:

Index and value togetherPop out in the code editor (opens in a new tab)JavaScript
const names = ["Ada", "Ben"];
for (const [index, name] of names.entries()) {
  console.log(index, name);
}

That loop reads like a sentence: “for each index-and-name pair of the names entries.” You avoid manually writing names[index], and your loop still supports break if a later condition needs it.

Holes: for...of visits, forEach skips
Step 0 of 11Ready
Your turn: follow the blue line

Sparse arrays are rare but important. Step through to see why for...of and forEach do not treat holes the same way.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
for (const item of lockers) {  console.log(item);}lockers.forEach((item) => {  console.log(item);});
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

Sparse arrays are uncommon in everyday UI code, but this edge case explains a lot of surprising output. for...of uses array iteration and visits the missing slot as undefined. Most array callback methods, including forEach, skip holes.

Array-likes & Array.from

INTERACTIVE

An array-like is an object with numbered slots and a length. It looks like a row of lockers, but it does not automatically have the array toolbelt. A plain object such as { 0: "a", 1: "b", length: 2 } is array-like; Array.isArray still says false.

Real-life analogyArray.from makes a real shopping list

Numbered slots tell you where to look, but they are not a real array. Array.from copies the visible slots into a real array, where its methods are available.

In real life: Items written in numbered places
In JavaScript: An array-like: 0, 1, and length
In real life: A list you can check and change
In JavaScript: Array methods such as map, filter, join, and slice
In real life: Rewrite the items on a real list
In JavaScript: Array.from(arrayLike) returning a real array

Where the analogy stops: Array.from copies values at that moment. If the original array-like changes later, the new array does not magically stay in sync.

Give an array-like the array toolbelt
Step 0 of 7Ready
Your turn: follow the blue line

An array-like can look like an array without owning array methods. Step through the conversion and the borrowed-method version.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
console.log(Array.isArray(row));try {  row.map((letter) => letter.toUpperCase());} catch (error) {  console.log(error.name);}const real = Array.from(row);console.log(real.map((letter) => letter.toUpperCase()).join(""));console.log(Array.prototype.map.call(row, (letter) => letter + "!").join("|"));console.log(Array.prototype.join.call("abc", "-"));
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

Array.from works with array-likes and iterables. Strings are both: they have indexed characters and a length, and they also work with for...of. A Set is iterable but not array-like, because it has no numeric slots and no array-style length.

Array, array-like, or neither?
  • ["a", "b"]
  • the arguments object inside a regular function
  • "abc"
  • { 0: "a", 1: "b", length: 2 }
  • document.querySelectorAll(section)
  • new Set([a, b])
  • { name: "Ada" }
Try it yourself
0 of 7 correct

Sort each value by its shape. Ask: is it a real Array? If not, does it have numbered slots and a length?

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Borrowing array methods for array-likes

PRACTICAL

Sometimes you do not need to keep the converted array. You only need one array method to read the indexed slots. JavaScript lets you borrow a method from Array.prototype and run it with a different receiver: Array.prototype.map.call(row, fn). In one sentence, call invokes a function while choosing what this means inside it; the later call, apply & bind lesson goes deeper.

Borrowing in one linePop out in the code editor (opens in a new tab)JavaScript
const row = { 0: "a", 1: "b", length: 2 };
const excited = Array.prototype.map.call(row, (letter) => letter + "!");
console.log(excited.join("|"));

console.log(Array.prototype.join.call("abc", "-"));

Borrowing is useful in tiny adapters and older code, but conversion is usually clearer for learners and teams: Array.from(row).map(fn). Use borrowing when you specifically want “run this array method once on this array-like value.” Use conversion when you will keep using array methods or pass the result around.

Prefer clear code

If a teammate has to pause at Array.prototype.map.call, Array.from(row).map may be the better choice. The tiny performance difference rarely matters in beginner-to-intermediate application code.

arguments & NodeList

LIVE BROWSER

Two array-likes show up in real code: arguments inside a regular function and NodeList from browser DOM methods such as querySelectorAll. You met arguments in Default & rest parameters. Today, prefer rest parameters when you control the function; they create a real array immediately.

arguments is array-like and iterablePop out in the code editor (opens in a new tab)JavaScript
function list() {
  console.log(Array.isArray(arguments));
  console.log([...arguments].join("|"));
  console.log(Array.from(arguments).map((value) => value * 2).join(","));
}
list(2, 4, 6);

In modern engines, spreading arguments works, so [...arguments] makes an array. Still, Array.isArray(arguments) is false, and arguments.map is missing. Rest parameters are cleaner: function list(...values) { ... } gives you a real values array.

A NodeList appears when browser code asks the DOM for a group of nodes. The DOM itself is taught later in Walking & searching the DOM, but the shape matters now: querySelectorAll returns a NodeList, not an Array.

Console version for a real pagePop out in the code editor (opens in a new tab)JavaScript
const sections = document.querySelectorAll("section");
console.log(sections.length);
console.log(typeof sections.forEach);
console.log(typeof sections.map);
const headings = Array.from(sections, (section) => section.id);
console.log(headings.join(", "));
Inspect a real NodeList on this lesson page
Browser console versionPop out in the code editor (opens in a new tab)JavaScript
const sections = document.querySelectorAll("section");console.log(sections.length);console.log(typeof sections.forEach);console.log(typeof sections.map);const headings = Array.from(sections, (section) => section.id);console.log(headings.join(", "));
Live NodeList factsready
sections.length
0
typeof sections.forEach
not checked yet
typeof sections.map
not checked yet
Array.from ids
Run the check to read this page.
Try it yourself

Click the button to ask the browser for every section element in this article.

The count may change if the page layout changes, but the shape is the important part: indexed nodes, a length, usually forEach, and no map.

In most modern browsers, NodeList has forEach but not map. That is why production code often says Array.from(document.querySelectorAll("button")) before mapping, filtering, or sorting nodes.

Where you will use this

Iteration choices show up anywhere you process UI data. Use for...of to validate fields until the first error, because you can break or return from the surrounding function. Use entries() when an error message needs “item 3” as well as the value. Use Array.from when browser APIs hand you an array-like collection.

A realistic validation loopPop out in the code editor (opens in a new tab)JavaScript
const fields = ["name", "email", "password"];
const values = ["Ada", "", "secret"];

for (const [index, value] of values.entries()) {
  if (value === "") {
    console.log(fields[index] + " is required");
    break;
  }
}

This is the comfortable middle ground: readable values, an index when you need it, and early exit when continuing would be noisy.

Common misconceptions

  • “return stops forEach.” It stops only the current callback call. The outer forEach keeps scheduling the remaining items.
  • “Array-like means Array.” Array-like means numbered slots plus length. Array.isArray can still be false.
  • “NodeList has all array methods because it has forEach.” In most browsers it has forEach, but methods such as map, filter, and reduce live on real arrays.
  • “for...in is the index loop for arrays.” It is a property-key loop. It can see non-index enumerable properties and returns keys as strings.
  • “Holes behave like explicit undefined values everywhere.” for...of visits holes as undefined, while forEach skips them.
  • “Borrowing is always better than converting.” Borrowing is compact but advanced. Array.from is often clearer, especially before several array operations.

Practice exercises

5 EXERCISES
Exercise 1 · Warm-upPredict what forEach with return does

Read the code and type the exact number printed.

Starter codePop out in the code editor (opens in a new tab)JavaScript
const scores = [3, 0, 4, -2, 5];
let total = 0;
scores.forEach((score) => {
  if (score === 0) return;
  if (score < 0) return;
  total += score;
});
console.log(total);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeConvert an array-like and map it

    Run or reason through the starter. It converts the row, maps each letter to uppercase, and prints the joined result.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const row = { 0: "x", 1: "y", length: 2 };
    const result = Array.from(row).map((letter) => letter.toUpperCase());
    console.log(result.join(""));

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeLoop with index and value via entries()

      What is the second line printed by this loop?

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      const pets = ["cat", "dog"];
      for (const [index, pet] of pets.entries()) {
        console.log(index + ":" + pet);
      }

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeCount real NodeList items on a page

        In the browser console, run the NodeList snippet from this lesson. Then answer which array method is missing directly on the NodeList.

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeBorrow join from Array

          Predict the output of the borrowed method call.

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          console.log(Array.prototype.join.call("abc", "-"));

          Answer, then press Check. Spacing and letter case don’t matter.

            Check your understanding

            8 QUESTIONS
            Iterating arrays quiz · 8 questionsScore: first tries count
            1. Question 1 of 8Which loop should you choose when you may need to stop as soon as a negative number appears?

              Choose an answer to see the explanation.

            2. Question 2 of 8What does the for...of total program print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const values = [1, 0, 2, -1, 9];
              let total = 0;
              for (const value of values) {
                if (value === 0) continue;
                if (value < 0) break;
                total += value;
              }
              console.log(total);

              Choose an answer to see the explanation.

            3. Question 3 of 8How many callback calls does this sparse-array forEach count?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const sparse = ["a", , "b"];
              let count = 0;
              sparse.forEach(() => {
                count += 1;
              });
              console.log(count);

              Choose an answer to see the explanation.

            4. Question 4 of 8Which expression gives [0, "Ada"] as the first pair for const names = ["Ada"]?

              Choose an answer to see the explanation.

            5. Question 5 of 8What does Array.from(row).join("-") print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const row = { 0: "a", 1: "b", length: 2 };
              console.log(Array.from(row).join("-"));

              Choose an answer to see the explanation.

            6. Question 6 of 8What does borrowed join print for the string "abc"?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log(Array.prototype.join.call("abc", "-"));

              Choose an answer to see the explanation.

            7. Question 7 of 8Inside a regular function in modern JavaScript, what is true about arguments?

              Choose an answer to see the explanation.

            8. Question 8 of 8A browser NodeList from querySelectorAll usually has which pair of features?

              Choose an answer to see the explanation.

            Key takeaways

            • Use for when index control matters most.
            • Use for...of for readable value loops that can still break or continue.
            • Use forEach for side effects on every existing item, not for early exit or producing a new array.
            • keys(), values(), and entries() return iterators; spread or Array.from reveals all their values.
            • Array-likes have numbered slots and length. Convert with Array.from when you want the full array toolbelt.

            Iteration is choosing the right way to visit items; array-like handling is choosing whether to convert first or borrow one method carefully.

            Up next: Destructuring arrays & objects.

            CompleteFrontend Clear concepts. Working examples.