Array.prototype.entries, keys and values

All three return an iterator rather than an array, which is why logging one shows "Object [Array Iterator] {}" instead of your data. entries is the only one most code ever needs.

Array methodsES2015Live demo
Common call
for (const [i, x] of items.entries())
Returns
an Array Iterator — lazy and single-use
Replaces
a manual index variable in a for...of loop
Watch out
an iterator is EXHAUSTED after one pass; it cannot be reused
array.entries() | array.keys() | array.values()
→ Array Iterator

Demo

Live evaluation
Try:
Inputs
itemsstring[]items, comma separated
methodstringentries, keys or values
Output
[...['a', 'b', 'c']['entries']()]
[[0, 'a'], [1, 'b'], [2, 'c']]

The demo spreads the iterator into an array so you can see what it yields — without the spread you would just get "Object [Array Iterator] {}". entries gives [index, value] pairs, keys gives the indices alone, and values gives the elements, which is what a plain for...of already does. That is why entries is the one worth remembering: it is the clean way to get the index alongside the element.

Common patterns

Index and value together
The main reason entries exists.
for (const [i, item] of items.entries()) {
  console.log(i, item);
}
Indices as an array
keys spread gives 0..n-1 without a range helper.
const indices = [...items.keys()];
A range of numbers
A common idiom for counting.
const range = [...Array(5).keys()];  // [0, 1, 2, 3, 4]

Examples

1. entries
[...['a', 'b'].entries()]
Returns
[[0, 'a'], [1, 'b']]
2. keys
[...['a', 'b'].keys()]
Returns
[0, 1]
3. values
[...['a', 'b'].values()]
Returns
['a', 'b']
4. Without spreading
['a'].entries()
Returns
Object [Array Iterator] {}
5. Stepping manually
['a'].entries().next()
Returns
{ value: [0, 'a'], done: false }
6. A counting range
[...Array(3).keys()]
Returns
[0, 1, 2]

Pitfalls

1. They return an iterator, not an array
Logging one shows Object [Array Iterator] {} rather than the contents, and array methods like map or length are not available on it. Spread it or loop it.
Not an array
['a', 'b'].entries().length
undefined
Spread first
[...['a', 'b'].entries()].length
2
2. An iterator is single-use
Once consumed it is exhausted — a second loop over the same iterator runs zero times. Call the method again for a fresh one.
Second pass empty
const it = items.entries();
[...it];
[...it]
[]
Fresh iterator
[...items.entries()];
[...items.entries()]
both populated
3. values() is usually redundant
for...of over an array already yields the elements, because values IS the default iterator. Writing it out adds noise without changing anything.
Redundant
for (const x of items.values()) { ... }
identical behaviour
Just iterate
for (const x of items) { ... }
same result
4. entries() is not Object.entries()
Array entries yields [index, value] pairs lazily; Object.entries returns a real array of [key, value] pairs. Similar names, different shapes and different types.
Different things
Object.entries(['a'])
[['0', 'a']] // string keys, real array
Array version
[...['a'].entries()]
[[0, 'a']] // number indices

When to use

Use it
  • Getting the index alongside the element in for...of — use entries
  • Producing a numeric range with [...Array(n).keys()]
  • Manual step-by-step iteration with .next()
Reach for something else
  • Plain iteration over elements → for...of directly, not values()
  • You want an array of pairs eagerly → Object.entries, or spread
  • You need to iterate twice → call the method again, or store the spread

Notes

Complexity
O(1) to create; O(n) to consume fully
Return
An Array Iterator; the array is never modified
CPython impl
V8: Builtins-array-iterator.tq
Memory
Lazy — nothing is materialised until you spread or loop
Thread-safe
Single-threaded; mutating the array mid-iteration gives undefined behaviour

FAQ

Because it is an iterator, not an array — a lazy object that produces values on demand and has nothing to display until consumed. Spread it into an array or loop over it to see the contents.

console.log([...items.entries()]);

History

ES2015
entries, keys and values added with the iteration protocol and for...of.