Array.prototype.entries()

Returns an iterator of [index, element] pairs, one for each position in the array.

Signature
entries()
  • Added in JavaScript ECMAScript 2015

Return value

Array IteratorA new iterable iterator object yielding a two-element [index, element] array for each index.

Errors

Throws a TypeError only if called on null or undefined.

entries() yields [index, element] pairs, which makes it the clean way to run a for...of loop that needs the position as well as the value. Destructure in the loop head and both are named:

for (const [i, item] of list.entries()) { … }

When to reach for it

Use it instead of forEach((item, i) => …) whenever the body needs break, continue, return, or await — none of which work meaningfully inside a forEach callback. It also pairs with Object.fromEntries() to turn a list into an index-keyed object.

What trips people up

  • Each iteration allocates a fresh two-element array. That is irrelevant for ordinary loops but noticeable in a hot path over millions of items, where a counting for loop is cheaper.
  • The iterator is single-use, like all array iterators.
  • Holes in a sparse array are yielded as [i, undefined] rather than skipped.
  • It is unrelated to Object.entries(), which returns an array of string-keyed pairs and skips empty slots.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Print a numbered list where the body may break early.
  • Await something per item inside a for...of loop that also needs the index.
  • Find the index of the first element matching a multi-step condition.
  • Build an index-keyed object with Object.fromEntries(list.entries()).

Frequently asked questions

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

Iterate arr.entries() and destructure the pair: for (const [i, value] of arr.entries()). Each step yields a two-element array holding the index and the element.

Should I use entries() or forEach() with an index?

Use entries() when the loop body needs break, continue, return, or await, since none of those work inside a forEach callback. forEach() is fine for a straightforward pass with no early exit.

Is Array.prototype.entries() the same as Object.entries()?

No. Array.prototype.entries() returns a single-use iterator of [numericIndex, value] pairs covering every position including holes, while Object.entries() returns a plain array of [stringKey, value] pairs and skips empty slots.

More examples

break and await, which forEach cannot do

The loop awaits each job in sequence and stops after index 1. Inside a forEach callback, break is a syntax error and await would not pause the outer function.

Example · javascript
const jobs = ["a", "b", "c", "d"];

for (const [i, job] of jobs.entries()) {
  const result = await Promise.resolve(job.toUpperCase());
  console.log(i, result);
  if (i === 1) break;
}

console.log("stopped early");

Sparse arrays and Object.entries()

entries() reports index 1 with an undefined value, Object.entries() omits it entirely, and forEach() skips it too. Only entries() gives you a pair for every position.

Example · javascript
const sparse = ["a", , "c"];

console.log([...sparse.entries()]);
console.log(Object.entries(sparse));

sparse.forEach((v, i) => console.log("forEach saw", i, v));

Comparing adjacent elements

Having the index in scope lets the body reach back to the previous element. continue skips the first reading, which has nothing to compare against.

Example · javascript
const readings = [3, 5, 5, 2, 9];

for (const [i, value] of readings.entries()) {
  if (i === 0) continue;
  const delta = value - readings[i - 1];
  console.log(`${i}: ${value} (${delta >= 0 ? "+" : ""}${delta})`);
}

Discussion

  • Be the first to comment on this lesson.