While basic loops (for
, for...of
, forEach
) are common, JavaScript provides powerful, low-level mechanisms for iteration that are essential for handling complex data structures, custom objects, and asynchronous data streams. This chapter explores iterators and generators, the backbone of modern data access.
1. Iterables and Iterators
An Iterable is any object that defines the [Symbol.iterator]
method (e.g., Arrays, Strings, Maps, Sets). An Iterator is an object returned by that method, which defines a next()
method for sequential access.
The next()
method always returns an object with two properties:
value
: The next item in the sequence.
done
: A boolean (true
if the sequence has finished, false
otherwise).
This mechanism is what powers the for...of
loop and the spread operator (...
).
JavaScript
const myArray = [10, 20];
const iterator = myArray[Symbol.iterator]();
console.log(iterator.next()); // Output: { value: 10, done: false }
console.log(iterator.next()); // Output: { value: 20, done: false }
console.log(iterator.next()); // Output: { value: undefined, done: true }
2. Custom Iterators (Making Objects Iterable)
You can make your own custom objects iterable by implementing the [Symbol.iterator]
method.
JavaScript
const team = {
manager: 'Sarah',
engineer: 'Tom',
designer: 'Leia',
// Implement the iterator protocol
[Symbol.iterator]: function* () {
yield this.manager;
yield this.engineer;
yield this.designer;
}
};
// The object can now be used in a for...of loop
for (const member of team) {
console.log(member);
}
// Output: Sarah, Tom, Leia
3. Generators (function*
and yield
)
Generators are special functions declared with function*
(the asterisk). When called, they don't execute immediately; they return a Generator Object, which is an iterator.
The yield
keyword is used within a generator function to pause execution and return a value. The function can be resumed later using the iterator's next()
method.
JavaScript
function* idGenerator() {
let id = 1;
while(true) {
// Pauses execution and returns the current value of 'id'
yield id++;
}
}
const generator = idGenerator();
console.log(generator.next().value); // Output: 1 (Execution pauses)
console.log(generator.next().value); // Output: 2 (Execution resumes and increments)
console.log(generator.next().value); // Output: 3
Generators are powerful for creating infinite data sequences or managing complex asynchronous flows (though async/await
largely replaced this use case).
4. Advanced Spread Operator (...
) Usage
The spread operator is closely tied to the iteration protocol. It works on any iterable object.
Shallow Cloning: Quickly create a new copy of an array or object.
JavaScript
const original = { a: 1, b: 2 };
const clone = { ...original }; // { a: 1, b: 2 }
Function Arguments (Rest Parameters): Collects a variable number of arguments into an array.
JavaScript
function logArgs(first, ...rest) {
console.log(rest); // [2, 3]
}
logArgs(1, 2, 3);