JavaScript Map, Set, Iterators and Generators Practice Quiz
Test JavaScript collections and iteration with 12 questions and three programs: Map and Set, WeakMap, the iteration protocol, generators and symbols.
- Course: JavaScript study plan
- Module: Collections and iteration
- Kind: Checkpoint — cleared at 70%
- Reading time: 24 min
- Runtime: Node 16
Checkpoint — Collections and iteration is the checkpoint that closes the Collections and iteration module: a graded quiz and whole-program exercises, passed at 70%.
Instructions
This checkpoint covers Map and Set (operations, SameValueZero, insertion order, the idioms and hand-written set algebra), the weak collections and why they cannot be iterated, the iteration protocol (Symbol.iterator, next(), done/value, laziness, return()), generators (yield, yield*, next(value), lazy pipelines), and symbols as keys and as the language's hooks.
How it works. Twelve questions and three programs; 70% on the questions and every program accepted clears the module.
Before you start, make sure you can answer:
- Map versus object; how Map compares keys; how to count, group and index with a Map.
- Why a WeakMap has no
sizeand takes only object keys; the three patterns it exists for. - The exact shape of an iterator; iterable versus iterator; what
breaktriggers. - What runs when a generator is called, what
yield*does, why the firstnext(v)argument is dropped. Symbol()versusSymbol.for(); which enumeration paths skip symbol keys; three well-known symbols.
The programs are an LRU cache built on a Map's insertion order, a graph explorer with adjacency sets and a breadth-first generator, and a small iterator toolkit — chunk, zip, enumerate, takeWhile — driven by commands.
Common questions
What is the exact shape of a JavaScript iterator?
An iterator is an object with a next() method that returns { value, done }: done: false with each value, then done: true once the sequence ends. It may also have an optional return() method, which break calls so the iterator can clean up.
Why is the argument to a generator's first next() ignored?
Calling a generator runs none of its body. The first next() starts it and runs to the first yield, so there is no paused yield to receive the argument, and it is dropped. Values sent with later next(v) calls become the results of the yield expressions.
Why does a WeakMap have no size and take only object keys?
Its entries disappear when their keys are garbage collected, and collection must not be observable, so there is no size and no iteration. Keys must be objects because a primitive can never become unreachable, so holding one weakly would mean nothing.
Exercises
An LRU cache on Map order
Implement LRUCache(capacity) over a private Map whose insertion order is the recency order (oldest first). get(key) returns the value (re-inserting the entry so it becomes newest) or -1; put(key, value) inserts or refreshes, then evicts the oldest entry when over capacity and returns the evicted key (else null); get size; entries() yields entries newest first. Line 1 is the capacity; then put k v (print evict <k> when something was evicted), get k (print get <k> -> <v|-1>), show (print [k=v, ...] size=<n> newest first).
Example: capacity 2, then put a 1, put b 2, get a, put c 3, get b, show, put a 10, show →
get a -> 1
evict b
get b -> -1
[c=3, a=1] size=2
[a=10, c=3] size=2A graph explorer with a breadth-first generator
Store an undirected graph as a Map from node to a Set of neighbours. Write a generator bfs(start) yielding [node, distance, parent] in breadth-first order, visiting neighbours in sorted order and each node once. Commands: edge a b; bfs a prints bfs a: <node@distance ...>; path a b reconstructs the shortest path from the parents (stop pulling from the generator as soon as b appears) and prints path a -> b: <nodes> (<n> hops) or path a -> b: none; degree a prints degree a = <neighbour count> (0 for an unknown node).
Example: edges a b, a c, b d, c d, d e, f g, then bfs a, path a e, path a g, degree d →
bfs a: a@0 b@1 c@1 d@2 e@3
path a -> e: a b d e (3 hops)
path a -> g: none
degree d = 3An iterator toolkit
Write four generators that work on any iterable: chunk(it, size) (arrays of size, the last possibly shorter), zip(...its) (arrays of the i-th items, stopping at the shortest), enumerate(it, start = 0) ([index, item] pairs) and takeWhile(pred, it). Input: line 1 numbers a, line 2 words b, line 3 a chunk size, line 4 a limit. Print chunks=<chunk(a, size)>, zip=<zip(a, b)>, enumerate=<enumerate(b, 1)>, takeWhile=<takeWhile(x => x < limit, a)> (all as JSON), then zipString=<zip("abc", a) as c+n pairs joined by ,>.
Example: 1 2 3 4 5 6 7 / red green blue / 3 / 5 →
chunks=[[1,2,3],[4,5,6],[7]]
zip=[[1,"red"],[2,"green"],[3,"blue"]]
enumerate=[[1,"red"],[2,"green"],[3,"blue"]]
takeWhile=[1,2,3,4]
zipString=a1,b2,c3In this module: Collections and iteration
- Map and Set — real keyed collections
- WeakMap, WeakSet and WeakRef — data that does not keep objects alive
- The iteration protocol — what for…of, spread and destructuring actually call
- Generators — functions that pause, and lazy pipelines
- Symbols — unique keys and the language's extension points
- Checkpoint — Collections and iteration (this lesson)
← Symbols — unique keys and the language's extension points · throw, try, catch, finally — the mechanics, precisely →