JavaScript iterators are incredibly versatile and can provide developers with greater control over how data collections or custom data structures are iterated over. This guide will walk you through creating a custom iterator from scratch.
An iterator in JavaScript is an object that follows the iterator protocol, which means it must contain a next()
method that returns an object with the following properties:
Here’s a simple example of an iterator:
const simpleIterator = {
current: 0,
next() {
if (this.current < 5) {
return { value: this.current++, done: false };
} else {
return { value: undefined, done: true };
}
}
};
console.log(simpleIterator.next()); // { value: 0, done: false }
console.log(simpleIterator.next()); // { value: 1, done: false }
console.log(simpleIterator.next()); // { value: undefined, done: true }
While many built-in JavaScript objects like arrays already implement iterators, there are cases when custom iterators are useful:
To create a custom iterator, the first step is to create an iterable object. Here’s an example where we define an iterator to loop over a collection of names:
const nameCollection = {
names: ['Alice', 'Bob', 'Charlie', 'David'],
index: 0,
next() {
if (this.index < this.names.length) {
return { value: this.names[this.index++], done: false };
} else {
return { value: undefined, done: true };
}
}
};
In this example, the iterator will return each name in sequence until all names are iterated over.
After creating the iterator, you can call the next()
method inside a loop to iterate through the values:
let result = nameCollection.next();
while (!result.done) {
console.log(result.value); // Output: Alice, Bob, Charlie, David
result = nameCollection.next();
}
The loop continues until all values in the collection have been processed.
To make the collection work with JavaScript’s for...of
loop, you can implement the Symbol.iterator
method:
const nameCollection = {
names: ['Alice', 'Bob', 'Charlie', 'David'],
[Symbol.iterator]() {
let index = 0;
return {
next() {
if (index < this.names.length) {
return { value: this.names[index++], done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
for (const name of nameCollection) {
console.log(name); // Output: Alice, Bob, Charlie, David
}
By implementing Symbol.iterator
, the object can now be used directly in a for...of
loop without manually calling next()
.
Let’s take the concept further with a custom iterator that generates Fibonacci numbers up to a given limit:
const fibonacci = {
limit: 100,
[Symbol.iterator]() {
let prev = 0, curr = 1;
return {
next() {
const value = curr;
[prev, curr] = [curr, prev + curr];
if (value <= this.limit) {
return { value, done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
for (const num of fibonacci) {
console.log(num); // Output: Fibonacci numbers up to 100
}
Creating custom JavaScript iterators gives developers the flexibility to manage how data is traversed, which is particularly useful for custom data structures, lazy evaluation, and processing data streams. By following the iterator protocol and utilizing Symbol.iterator
, you can create custom iterators that work seamlessly with JavaScript’s built-in iteration syntax, leading to more maintainable and efficient code.
Published By: Ibrahim
Updated at: 2024-10-08 23:46:14
Frequently Asked Questions:
1. What is the difference between an iterable and an iterator in JavaScript?
An iterable is an object that defines how its elements can be iterated over using a special Symbol.iterator method. Examples include arrays and strings. An iterator, on the other hand, is an object returned by the Symbol.iterator method that contains a next() method, which returns the next item in the sequence with a value and a done status.
2. How does the done property work in JavaScript iterators?
The done property is a boolean that indicates whether the iterator has completed its sequence. If done: false, it means there are more values to iterate over. If done: true, it signifies that the iteration is complete, and no more values will be returned.
3. Can you use a custom iterator with the for...of loop?
Yes, you can use a custom iterator with the for...of loop, but to do so, you need to implement the Symbol.iterator method in your object. This allows the object to be treated like an iterable and used with for...of.
4. When should I consider creating a custom iterator in JavaScript?
You should create a custom iterator when you need more control over how a collection or sequence of values is traversed. Custom iterators are especially useful for iterating over complex data structures, implementing lazy evaluation, or handling streams of data where values are generated on the fly.