Map.prototype.keys()
Returns an iterator over the map's keys in insertion order.
keys()- Added in JavaScript ES2015
Return value
Map IteratorA new iterable iterator object yielding each key in the map, in insertion order.
Errors
Throws a TypeError when called on a value that is not a real Map.
Changelog
- PHP ES2015Introduced with the Map built-in.
- PHP ES2025Iterator helper methods such as map(), filter() and take() became available on the returned iterator via Iterator.prototype.
keys() gives you an iterator, not an array. That trips people up immediately: there is no .length, no .map() in older engines, and no index access. Spread it or wrap it — [...map.keys()] or Array.from(map.keys()) — whenever you want array methods such as sort() or join().
It is live and single-use
The iterator reads the map as it goes rather than snapshotting it. Entries added after you created the iterator but before it finishes are still yielded; entries deleted in the meantime are skipped. It is also exhausted once consumed — a second spread of the same iterator variable produces an empty array, which is why you usually call map.keys() fresh each time rather than storing it.
When to reach for it
Use keys() when you only care about which keys exist: comparing two maps, building a sorted index, or feeding the key list to something else. If you need both halves, iterate the map directly — for (const [k, v] of map) — rather than looking each value up by key.
Example
When to use it
- Collect the map's keys into a sorted array for display
- Compare which keys two maps have in common
- Take the oldest key from an insertion-ordered cache
- Feed the key list to Set operations or a join()
Frequently asked questions
How do I turn Map keys into an array?
Spread or convert the iterator: [...map.keys()] or Array.from(map.keys()). keys() itself returns an iterator, which has no length and no array methods.
Are Map keys returned in a guaranteed order?
Yes, always in insertion order. Overwriting an existing key does not change its position; deleting and re-adding it moves it to the end.
Why is my Map keys iterator empty the second time?
An iterator is consumed once. After you spread or loop over it, it is exhausted — call map.keys() again for a fresh one.
More examples
Comparing the keys of two maps
Putting one map's keys in a Set makes the membership test constant time. The last line spreads both key iterators into a Set to get the union without duplicates, in first-seen order.
const a = new Map([["x", 1], ["y", 2]]);
const b = new Map([["y", 9], ["z", 8]]);
const bKeys = new Set(b.keys());
const shared = [...a.keys()].filter((k) => bKeys.has(k));
const onlyInA = [...a.keys()].filter((k) => !bKeys.has(k));
console.log(shared);
console.log(onlyInA);
console.log([...new Set([...a.keys(), ...b.keys()])]);The iterator follows later changes
Because the iterator walks the live map, "b" never appears and "c" does. Snapshot with [...map.keys()] first if you intend to mutate the map while looping.
const m = new Map([["a", 1], ["b", 2]]);
const it = m.keys();
console.log(it.next().value); // "a"
m.delete("b"); // not reached yet — skipped
m.set("c", 3); // added at the end — will be yielded
console.log([...it]); // ["c"]
console.log([...m.keys()]); // ["a", "c"]
Discussion