JavaScript > ES6 and Beyond > Iterators and Generators > Iterator protocol
Implementing the Iterator Protocol
This code snippet demonstrates how to implement the iterator protocol in JavaScript using ES6 syntax. We'll create a custom iterator for an array, showcasing the next()
method and the done
property.
Understanding the Iterator Protocol
The iterator protocol defines a standard way to produce a sequence of values (either finite or infinite) in JavaScript. An object is considered an iterator when it implements a next()
method with the following properties:next()
: A function that returns an object with two properties:value
: The next value in the sequence.done
: A boolean indicating whether the iterator has completed iterating through the sequence. If done
is true
, the value
property is usually omitted or undefined.
Creating a Custom Array Iterator
This code defines a class ArrayIterator
that implements the iterator protocol for an array. The constructor
initializes the array and the current index. The next()
method returns the next element of the array if the index is within the bounds of the array. Otherwise, it returns an object with done
set to true
and value
set to undefined
.
class ArrayIterator {
constructor(array) {
this.array = array;
this.index = 0;
}
next() {
if (this.index < this.array.length) {
return {
value: this.array[this.index++],
done: false
};
} else {
return {
value: undefined,
done: true
};
}
}
}
// Example Usage
const myArray = [10, 20, 30];
const iterator = new ArrayIterator(myArray);
console.log(iterator.next()); // Output: { value: 10, done: false }
console.log(iterator.next()); // Output: { value: 20, done: false }
console.log(iterator.next()); // Output: { value: 30, done: false }
console.log(iterator.next()); // Output: { value: undefined, done: true }
Concepts Behind the Snippet
This snippet demonstrates the core principles of the iterator protocol:index
) to keep track of its position in the sequence.next()
method only computes the next value when it's called, allowing for efficient processing of potentially large or infinite sequences.for...of
loops.
Real-Life Use Case Section
Iterators are heavily used in scenarios where you need to process a large dataset sequentially without loading it all into memory at once. Examples include:
Best Practices
Interview Tip
When asked about iterators and generators in an interview, be prepared to explain the iterator protocol, its benefits (e.g., lazy evaluation, memory efficiency), and how to implement a custom iterator. Demonstrate your understanding of the next()
method and the done
property. Also, be prepared to discuss the differences between iterators and generators, and when one might be preferred over the other.
When to use them
Use iterators when you need to:
Avoid iterators if you need to access elements randomly or if the entire dataset fits comfortably in memory and can be processed more efficiently using array methods.
Memory footprint
Iterators are generally memory-efficient because they only generate values on demand. This is particularly beneficial when dealing with large datasets or infinite sequences. They avoid the need to store the entire sequence in memory, reducing memory consumption.
Alternatives
Alternatives to iterators include:for
loops or forEach
methods can be used.
Pros
Cons
FAQ
-
What is the purpose of the `done` property in the iterator protocol?
Thedone
property indicates whether the iterator has finished iterating through the sequence. Whendone
istrue
, it signals that there are no more values to be retrieved from the iterator. -
Can I modify the underlying data structure while iterating over it using an iterator?
It's generally not recommended to modify the underlying data structure while iterating over it, as this can lead to unpredictable behavior and potentially cause the iterator to skip or repeat elements. -
What's the difference between an iterator and an iterable?
An iterable is an object that can be iterated over, meaning it has a method (typically namedSymbol.iterator
) that returns an iterator. An iterator is an object that implements thenext()
method according to the iterator protocol. In essence, an iterable provides a way to obtain an iterator.