🎯 Learning Objectives
By the end of this lesson, you will be able to:
- Understand iterator protocol and iterable objects
- Create custom iterators using Symbol.iterator
- Use generator functions with yield
- Implement lazy evaluation with generators
- Create infinite sequences
- Build custom data structures with iteration
📚 Iterator Protocol
Making Objects Iterable
class NumberRange {
constructor(start, end) {
this.start = start;
this.end = end;
}
[Symbol.iterator]() {
let current = this.start;
const end = this.end;
return {
next() {
if (current <= end) {
return { value: current++, done: false };
} else {
return { done: true };
}
}
};
}
}
// Usage
const range = new NumberRange(1, 5);
for (const num of range) {
console.log(num); // 1, 2, 3, 4, 5
}
🔄 Generator Functions
Basic Generators
function* numberGenerator() {
yield 1;
yield 2;
yield 3;
}
const gen = numberGenerator();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
console.log(gen.next().done); // true
Infinite Generator
function* fibonacci() {
let a = 0, b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
🎯 Practice Exercises
Exercise 1: Custom Collection
Create a custom collection with iteration:
Solution:
class CustomCollection {
constructor() {
this.items = [];
}
add(item) {
this.items.push(item);
}
*[Symbol.iterator]() {
for (const item of this.items) {
yield item;
}
}
*filter(predicate) {
for (const item of this.items) {
if (predicate(item)) {
yield item;
}
}
}
*map(transform) {
for (const item of this.items) {
yield transform(item);
}
}
}
// Usage
const collection = new CustomCollection();
collection.add({ name: 'Alice', age: 30 });
collection.add({ name: 'Bob', age: 25 });
collection.add({ name: 'Charlie', age: 35 });
// Iterate over all items
for (const person of collection) {
console.log(person.name);
}
// Filter and map
const adults = collection.filter(person => person.age >= 30);
const names = collection.map(person => person.name);
🎯 Key Takeaways
- Symbol.iterator makes objects iterable
- Generator functions use yield to pause execution
- Lazy evaluation improves memory efficiency
- Custom iterators enable flexible iteration
- Infinite sequences are possible with generators
Next Lesson: Lesson 5: Map, Set, WeakMap, WeakSet