Array.prototype.entries()
entries() The entries() method returns a new array iterator that contains the key-value pairs for each index in the array. This allows you to iterate over both the index and the value of each element in a single pass.
Syntax
array.entries()
Parameters
None. This method takes no parameters. The returned iterator always starts at index 0 and walks forward through every position in order, so there is no need for configuration options. Each call to entries() produces a fresh iterator that begins at the start of the array.
Examples
Basic usage with iterator
const fruits = ['apple', 'banana', 'cherry'];
const iterator = fruits.entries();
console.log(iterator.next().value);
// [0, 'apple']
console.log(iterator.next().value);
// [1, 'banana']
console.log(iterator.next().value);
// [2, 'cherry']
While next() gives fine-grained control over the iterator, most real-world code uses for...of to consume all entries in one pass instead. The destructuring [index, value] pattern is idiomatic here — it unpacks each pair without requiring manual .next() calls.
Using for…of loop
const colors = ['red', 'green', 'blue'];
for (const [index, value] of colors.entries()) {
console.log(`Index ${index}: ${value}`);
}
// Index 0: red
// Index 1: green
// Index 2: blue
Sometimes you want a snapshot of all index-value pairs as a static array — for passing to functions that expect arrays or for serialization. Spreading the iterator into an array literal produces a flat [[0, v0], [1, v1], ...] structure.
Converting to an array of pairs
const nums = [10, 20, 30];
const pairs = [...nums.entries()];
console.log(pairs);
// [[0, 10], [1, 20], [2, 30]]
Combining entries() with a for...of loop lets you act on both the position and the value simultaneously. This is especially useful for conditional early exits — you can break as soon as you find the element that matches your criterion instead of scanning the whole array.
Finding index with value condition
const data = [5, 12, 8, 130, 44];
for (const [index, value] of data.entries()) {
if (value > 100) {
console.log(`Found ${value} at index ${index}`);
break;
}
}
// Found 130 at index 3
When you need to select elements based on their position rather than their value, entries() pairs naturally with filter and map. This separates the position check from the value extraction, keeping the pipeline logic clean and avoiding a separate index-tracking variable.
Filtering by index
const items = ['a', 'b', 'c', 'd', 'e'];
// Get items at odd indices
const oddItems = [...items.entries()]
.filter(([index]) => index % 2 === 1)
.map(([, value]) => value);
console.log(oddItems); // ['b', 'd']
Index-aware transformations go beyond filtering — you can use the position to scale, weight, or offset each element. Spreading entries() and then calling map with destructured [index, value] parameters is a concise way to apply position-dependent logic without a separate counter variable.
Transforming with index awareness
const numbers = [1, 2, 3, 4, 5];
// Multiply each number by its index
const indexed = [...numbers.entries()].map(([i, n]) => n * i);
console.log(indexed); // [0, 2, 6, 12, 20]
Detecting duplicates and reporting their positions is a practical use case where entries() really helps. By iterating with a Set for tracking already-seen values, you can identify second and later occurrences and log where they appear — something indexOf cannot do without repeated scans over the array.
Practical: finding duplicate indices
const arr = [1, 2, 3, 2, 4, 3, 5];
const seen = new Set();
for (const [index, value] of arr.entries()) {
if (seen.has(value)) {
console.log(`Duplicate ${value} at index ${index}`);
} else {
seen.add(value);
}
}
// Duplicate 2 at index 3
// Duplicate 3 at index 5
You can also flow entries() data into object construction. The example below uses Object.fromEntries() paired with index-based lookup into a parallel values array, producing a plain object where keys come from one array and values from another — a pattern that avoids explicit loops for mapping two arrays together.
Object creation from entries
const keys = ['name', 'age', 'city'];
const values = ['Alice', 30, 'NYC'];
const obj = Object.fromEntries(keys.entries().map(([i, k], _, arr) =>
[k, values[i]]
));
console.log(obj); // { name: 'Alice', age: 30, city: 'NYC' }
When to use entries()
entries() is most useful when the index is meaningful to the computation — for example, alternating behavior based on even/odd index, labelling items with their position, or pairing elements from two arrays by index. When you only need the values, use values() or iterate the array directly. When you only need the indices, use keys().
const labels = ['first', 'second', 'third'];
const values = [10, 20, 30];
const labelled = [...labels.entries()].map(([i, label]) => ({
label,
value: values[i]
}));
// [{ label: 'first', value: 10 }, ...]
Iterator lifecycle
The iterator returned by entries() is consumed once. After iterating it fully, subsequent calls to next() return { done: true, value: undefined }. To iterate again, call entries() again to get a fresh iterator. Unlike arrays that you can loop over repeatedly, iterator objects track their own internal position and cannot be rewound.
const arr = [1, 2, 3];
const iter = arr.entries();
console.log([...iter]); // [[0,1],[1,2],[2,3]]
console.log([...iter]); // [] -- iterator exhausted
This is why spreading into an array or using it in a single for...of is the most common pattern — you rarely need to pause and resume the iterator manually.
entries() on sparse arrays
For sparse arrays, entries() visits every slot from 0 to length - 1, including holes. Holes are yielded as [index, undefined], unlike methods such as forEach and map that skip holes entirely. This means entries() gives you a consistent view of every position in the array, which can be useful when you need to distinguish between a missing slot and an explicit undefined value.
const sparse = [1, , 3];
for (const [i, v] of sparse.entries()) {
console.log(i, v); // 0 1, 1 undefined, 2 3
}
entries() vs keys() vs values()
All three methods return iterators that consume the array in the same order (index 0 to length-1). Use keys() when you only need the indices — for example, to generate a range of numbers or track positions. Use values() when you need the elements without their positions — equivalent to [...arr] but lazy. Use entries() when you need both, avoiding a separate indexOf call inside the loop to recover the index.
See Also
- Array.prototype.keys() — iterate over indices only
- Array.prototype.values() — iterate over values only