In-depth Reading of “Iterator Iterable”
Why you need an iterator
Because for ... of
it is very convenient to loop through arrays, but it would be too troublesome if only arrays supported this syntax. For example, we would naturally want to be able to for ... of
traverse each character of the string and hope new Set([1, 2, 3])
to quickly initialize a new one Set
.
JS supports all the capabilities mentioned above, so why does the JS engine know how to traverse strings? How to know the correspondence between the array [1, 2, 3]
and Set
each Key of the type? The principle behind implementing these functions is Iterables.
Because Array
both Set
are iterable, they can all be for ... of
traversed, and the JS engine naturally knows the mutual conversion relationship between them.
How iterators are designed
There are two ways to define iterators, namely defining them independently and combining them in an object.
independent definition
Just extend the properties for the object [Symbol.iterator]
. The reason why is adopted in the specification [Symbol.iterator]
is to prevent the ordinary literal Key from conflicting with the object's own OwnProperties:
const obj = {}
obj[Symbol.iterator] = function() {
return {
someValue: 1,
next() {
// This value can be accessed and modified through this.someValue,
// and any number of variables can be defined as auxiliary variables
// during the iteration process
if (...) {
// Indicates that the iteration is not over yet and the current value is value
return { done: false, value: this.current++ }
}
return { done: true } // Indicates that the iteration is completed
}
};
};
At for ... of
, done: true
it will continue to loop as long as it is not read.
Merge is defined in the object
To simplify it a bit, you can define iteration in an object:
let range = {
from: 1,
to: 5,
[Symbol.iterator]() {
this.current = this.from;
return this;
},
next() {
if (this.current <= this.to) {
return { done: false, value: this.current++ }…