Iterators & Generators

📖 Concept

Iterators are objects that define a sequence of values and a return value upon completion. Any object with a next() method that returns { value, done } is an iterator.

Generators are special functions that can pause and resume execution. Declared with function* and use yield to produce values lazily.

The Iteration Protocol: An object is iterable if it has a [Symbol.iterator]() method that returns an iterator. Arrays, strings, Maps, Sets are all iterable.

🏠 Real-world analogy: A generator is like a bookmark in a book. You can read a few pages (yield values), close the book, come back later, and continue exactly where you left off.

💻 Code Example

codeTap to expand ⛶
1// Custom iterator
2const range = {
3 from: 1,
4 to: 5,
5 [Symbol.iterator]() {
6 let current = this.from;
7 const last = this.to;
8 return {
9 next() {
10 return current <= last
11 ? { value: current++, done: false }
12 : { done: true };
13 }
14 };
15 }
16};
17for (const n of range) console.log(n); // 1, 2, 3, 4, 5
18
19// Generator function
20function* numberGenerator() {
21 yield 1;
22 yield 2;
23 yield 3;
24}
25const gen = numberGenerator();
26console.log(gen.next()); // { value: 1, done: false }
27console.log(gen.next()); // { value: 2, done: false }
28console.log(gen.next()); // { value: 3, done: false }
29console.log(gen.next()); // { value: undefined, done: true }
30
31// Infinite generator
32function* fibonacci() {
33 let [a, b] = [0, 1];
34 while (true) {
35 yield a;
36 [a, b] = [b, a + b];
37 }
38}
39// Take first 10 fibonacci numbers
40function take(gen, n) {
41 const result = [];
42 for (const val of gen) {
43 result.push(val);
44 if (result.length >= n) break;
45 }
46 return result;
47}
48console.log(take(fibonacci(), 10));
49
50// Generator with input (two-way communication)
51function* conversation() {
52 const name = yield "What is your name?";
53 const age = yield `Hello ${name}! How old are you?`;
54 return `${name} is ${age} years old.`;
55}
56const chat = conversation();
57console.log(chat.next()); // { value: "What is your name?", done: false }
58console.log(chat.next("Alice")); // { value: "Hello Alice!...", done: false }
59console.log(chat.next(25)); // { value: "Alice is 25...", done: true }
60
61// Delegating generators
62function* inner() { yield "a"; yield "b"; }
63function* outer() { yield 1; yield* inner(); yield 2; }
64console.log([...outer()]); // [1, "a", "b", 2]

🏋️ Practice Exercise

Mini Exercise:

  1. Create a generator that yields an infinite sequence of unique IDs
  2. Implement a custom iterable Range class
  3. Write a generator-based take(n) and filter(fn) for lazy evaluation
  4. Use a generator to flatten a deeply nested array

⚠️ Common Mistakes

  • Forgetting the * in function* — without it, yield is a syntax error

  • Calling a generator function returns an iterator, NOT the result — you must call next() or use for...of

  • Not understanding that for...of ignores the return value of a generator (only yield values)

  • Creating infinite generators without a termination condition in the consumer — infinite loop!

  • Confusing yield (pauses and returns) with return (ends the generator)

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for Iterators & Generators. Login to unlock this feature.