jsguides

Set.prototype.entries()

set.entries()

The entries() method returns a new Set Iterator containing [value, value] pairs for each value in the Set, in insertion order. This method exists primarily for consistency with the Map API, since Sets don’t have traditional key-value pairs.

Return Type

Set.prototype.entries() returns a new Iterator object that yields [value, value] arrays. Each entry is an array where both the first and second elements are the same—the Set’s value. The iterator maintains the insertion order in which values were added to the Set.

You can consume the iterator using for...of loops, the spread operator [...set.entries()], or by calling next() directly.

Key Quirk

Unlike Map.prototype.entries(), which returns [key, value] pairs where keys and values can differ, Set.prototype.entries() returns [value, value] because Sets only store values, not key-value pairs. This design maintains API consistency with Map while reflecting that Sets have no traditional keys.

const set = new Set(['a', 'b', 'c']);
[...set.entries()];
// [['a', 'a'], ['b', 'b'], ['c', 'c']]

entries() takes no arguments — it simply opens an iterator over the Set. Unlike Map.prototype.entries(), the pairs it yields have identical first and second elements, since Sets store values without a separate key. The method signature matches Map for API consistency.

Syntax

set.entries()

The examples below show the method in action. Destructuring [key, value] in a for...of loop works with Sets even though both positions hold the same value — this is what makes generic Map/Set iteration code possible.

Examples

Basic iteration with for…of

Destructuring [key, value] from each entry shows that both variables receive the same string. In a Map the two would differ, but the destructuring pattern itself works identically regardless of which collection you iterate.

const animals = new Set(['dog', 'cat', 'bird']);

for (const [key, value] of animals.entries()) {
  console.log(`${key} -> ${value}`);
}
// dog -> dog
// cat -> cat
// bird -> bird

Calling next() directly lets you advance the iterator manually, which is useful when you don’t want to consume every entry at once. Each call returns the next [value, value] pair wrapped in { value, done } until the iterator is exhausted.

Manual iteration with next()

const set = new Set([1, 2, 3]);
const iterator = set.entries();

console.log(iterator.next().value); // [1, 1]
console.log(iterator.next().value); // [2, 2]
console.log(iterator.next().value); // [3, 3]
console.log(iterator.next().done);   // true

The [value, value] design becomes clearer when you compare Set and Map iterators side by side. Map yields distinct key and value entries, while Set repeats its value in both slots — the same iterator protocol, but different semantics.

Comparison with Map.entries()

// Map: distinct key and value
const map = new Map([['a', 1], ['b', 2]]);
console.log([...map.entries()]);
// [['a', 1], ['b', 2]]

// Set: key and value are identical
const set = new Set(['a', 'b']);
console.log([...set.entries()]);
// [['a', 'a'], ['b', 'b']]

entries() vs values() vs keys()

A Set provides three iteration methods that all yield values in insertion order. They differ only in what each iteration step produces:

  • values() — yields each value once: 'a', 'b', 'c'
  • keys() — aliases to values() for Sets; same output
  • entries() — yields [value, value] pairs: ['a', 'a'], ['b', 'b']
const s = new Set(['x', 'y']);

[...s.values()];   // ['x', 'y']
[...s.keys()];     // ['x', 'y']
[...s.entries()];  // [['x', 'x'], ['y', 'y']]

In practice, you will almost always use values() or a plain for...of loop directly on the Set. entries() exists so that code written generically for both Map and Set — such as a helper that destructures [key, value] — works on a Set without branching.

Why the [value, value] design

When the iteration protocol was designed for ES6, Map and Set were given matching method names so that generic code could iterate either. A Map yields [key, value]; a Set has no keys, so it repeats the value in both positions to maintain a consistent shape. This means a function that does for (const [k, v] of collection.entries()) works whether collection is a Map or a Set — the only difference is that for a Set, k === v.

Iterating insertion order

entries() always yields values in the order they were added. Deleting and re-adding a value moves it to the end:

const s = new Set(['a', 'b', 'c']);
s.delete('a');
s.add('a');
[...s.values()]; // ['b', 'c', 'a']

See Also