Set.prototype.values()
Returns an iterator that yields every value in insertion order, one at a time.
values()- Added in JavaScript ES2015
Return value
Set IteratorA new iterable iterator object that yields the value of each element in insertion order.
Errors
Throws a TypeError if called on a value that is not a real Set instance.
values() hands back a fresh set iterator over the elements in insertion order. keys() is an alias for the exact same function, and so is Set.prototype[Symbol.iterator] — all three are literally the same function object. That is why for...of and spread work on a collection directly, and why you rarely need to call this method by name.
When you do need it
Call it when you want to pull values manually rather than loop: grabbing just the first element with s.values().next().value, interleaving two collections, or handing a lazy sequence to something that consumes iterators. It avoids materialising an array you would immediately throw away.
The trap
The returned iterator is single-use and stateful. Once drained it stays done — a second spread of the same iterator gives an empty array, and re-adding values to the collection will not revive it. Call values() again for a fresh pass. It is also live until exhausted: values added ahead of the cursor during iteration will be yielded, and values deleted before the cursor reaches them will not.
Being iterable itself, the iterator can be used directly in for...of or spread — no need to wrap it.
Example
When to use it
- Pluck the first element out of a collection without building an array
- Step through values manually while merging two ordered sequences
- Pass a lazy sequence to a function that accepts any iterable
- Confirm insertion order is preserved after a series of adds and deletes
Frequently asked questions
What is the difference between Set values() and keys()?
There is none — for a Set they are the same function object, because a Set has no separate keys. keys() exists only to keep the API shaped like Map's.
Why does spreading the same set iterator twice give an empty array?
Because a set iterator is single-use: the first spread drains it and it stays done forever after. Call values() again to get a fresh iterator over the current contents.
Do I need values() to loop over a Set?
No. Set.prototype[Symbol.iterator] is the same function, so for...of and spread work on the collection directly. Call values() when you want to pull elements manually via next().
More examples
Taking the first value without copying
Both routes give "first", but the iterator version does not build a throwaway array of every element. On an empty collection next() returns {value: undefined, done: true}, so reading .value yields undefined rather than throwing.
const queue = new Set(["first", "second", "third"]);
console.log(queue.values().next().value);
console.log([...queue][0]);
const empty = new Set();
console.log(empty.values().next());
console.log(empty.values().next().value);The iterator tracks live changes
After yielding "a", the deletion of "b" means the cursor skips straight to the newly added "c", then reports done. Calling values() again starts over and shows the current contents.
const s = new Set(["a", "b"]);
const it = s.values();
console.log(it.next().value);
s.add("c");
s.delete("b");
console.log(it.next().value);
console.log(it.next().done);
// A fresh call gives a fresh pass
console.log([...s.values()]);Interleaving two collections manually
Pulling from two iterators by hand is exactly the case values() exists for — neither collection is copied into an array first. The output alternates until the shorter side runs out, then drains the remainder.
const left = new Set([1, 3, 5]);
const right = new Set([2, 4]);
const a = left.values();
const b = right.values();
const merged = [];
let x = a.next();
let y = b.next();
while (!x.done || !y.done) {
if (!x.done) {
merged.push(x.value);
x = a.next();
}
if (!y.done) {
merged.push(y.value);
y = b.next();
}
}
console.log(merged);
Discussion