
Итерация — это процесс непрерывного извлечения данных из набора данных в определенном порядке.
Так в чем же разница между итерацией и обходом?
В JavaScript итератор — это объект, который может вызвать next метод для реализации итерации. возвращает объект An с двумя свойствами.
value : следующее значение итерируемого объекта.done : указывает, все ли данные были получены. false означает, что данные еще есть, true означает, что позже данных не будет.для генерации итераторов с помощью функции фабрики итераторов Symbol.iterator в итерируемом объекте.
const arr = []console.log(arr)

константа обр = [1, 2, 3]
const iter1 = arr[Symbol.iterator]() // Генерируем итератор с помощью функции фабрики итераторов `Symbol.iterator`.
console.log(iter1)
console.log(iter1.next())
console.log(iter1.next())
console.log(iter1.next())
console.log(iter1.next())
console.log('%c%s', 'color:red;font-size:24px;', '===============')
const mymap = новая карта()
mymap.set('имя', 'clz')
mymap.set('возраст', 21)
const iter2 = mymap[Symbol.iterator]() // Генерируем итератор с помощью функции фабрики итераторов `Symbol.iterator`.
console.log(iter2)
console.log(iter2.next())
console.log(iter2.next())
console.log(iter2.next()) 
Можно обнаружить, что итератор завершается после принятия последнего значения, то есть когда следующее value итератора undefined .
Однако приведенный выше оператор не очень точен. Он не завершается, когда следующее value итератора undefined . Вам также необходимо определить, действительно ли значение отсутствует или в итерируемом объекте есть значение, undefined . Если в итерируемом объекте есть undefined значение, он не будет завершен в этот момент.
const arr = [1, 2, 3, не определено] const iter1 = arr[Symbol.iterator]() // Генерируем итератор с помощью функции фабрики итераторов `Symbol.iterator`. console.log(iter1) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next())

могут вызывать функцию фабрики итераторов несколько раз, не мешая друг другу, создавая несколько итераторов. Каждый итератор представляет собой однократный упорядоченный обход итерируемого объекта. Различные итераторы не мешают друг другу и будут перемещаться только по итерируемым объектам независимо друг от друга .
константа обр = [1, 2, 3]
const iter1 = arr[Symbol.iterator]() // Генерируем итератор с помощью функции фабрики итераторов `Symbol.iterator`.
const iter2 = arr[Symbol.iterator]()
console.log('Итератор1:', iter1.next())
console.log('Итератор2:', iter2.next())
console.log('Итератор1:', iter1.next())
console.log('Итератор2:', iter2.next()) 
const arr = [1, 2, 3]
const iter = arr[Symbol.iterator]()
for (const i of iter) {
console.log(i) // Вывод 1, 2, 3 последовательно
} Если итерируемый объект модифицируется в ходе итерации, то результат, полученный итератором, также будет модифицирован.
константа обр = [1, 2, 3] console.log(обр.) const iter = arr[Symbol.iterator]() console.log(iter.next()) обр[1] = 999 console.log(iter.next()) console.log(iter.next())

Когда мы выполним итерацию done: true , будет ли сообщено об ошибке при вызове next или ничего не будет возвращено?
Однако нет, итератор будет в завершенном, но не завершенном состоянии. done: true означает, что он был завершен, но next все еще может быть вызван в будущем, хотя результатом всегда будет { value: undefined, done: true } . Вот почему говорят , что это сделано, но не сделано .
константа обр = [1, 2, 3] const iter = arr[Symbol.iterator]() console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next())

Из приведенного выше примера мы можем знать, что итератор генерируется с помощью фабричной функции итератора Symbol.iterator , поэтому нам нужно реализовать фабричную функцию итератора итератора, а затем итератор может вызвать next метод, поэтому вам также необходимо реализовать next метод. Что касается фабричной функции итератора, то она фактически возвращает экземпляр this напрямую.
Пример счетчика:
класс Counter {
конструктор (предел) {
это.count = 1
this.limit = предел }
следующий() {
если (this.count <= this.limit) {
возвращаться {
сделано: ложь,
значение: this.count++
}
} еще {
return {готово: правда, значение: неопределенное }
}
}
[Символ.итератор]() {
верните это
}} const counter = новый счетчик (3) const iter = counter[Symbol.iterator]() console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next())

На первый взгляд проблемы нет, но если мы используем for-of для обхода, мы можем найти проблему.
const counter = new Counter(3)for (пусть i счетчика) {
console.log(i)}console.log('Еще одна итерация:')for (пусть i счетчика) {
console.log(i)} 
Использование цикла for-of также делает его одноразовым. Это связано с тем, что count является переменной этого экземпляра, поэтому в обеих итерациях используется одна и та же переменная. Однако после первого цикла переменная превысила предел, поэтому вы ничего не получите, используя цикл for-of . снова. Результат был.
Вы можете поместить переменную count в замыкание, а затем вернуть итератор через замыкание, чтобы каждый созданный итератор соответствовал новому счетчику.
класс Счетчик {
конструктор (предел) {
this.limit = предел }
[Символ.итератор]() {
пусть счетчик = 1
const limit = this.limit return {
// Фабричная функция итератора должна возвращать объект со следующим методом, поскольку итерация фактически реализуется путем вызова следующего метода next() {
если (счет <= предел) {
возвращаться {
сделано: ложь,
значение: счетчик++
}
} еще {
return {готово: правда, значение: неопределенное }
}
}
}
}} Test
const counter = new Counter(3)for (пусть i счетчика) {
console.log(i)}console.log('Еще одна итерация:')for (пусть i счетчика) {
console.log(i)} 
аналогично использованию цикла for-of . Итератор разумно вызывает next метод. Когда итератор завершается раньше, он также вызывает метод return .
[Символ.итератор]() {
пусть счетчик = 1
const limit = this.limit return {
// Фабричная функция итератора должна возвращать объект со следующим методом, поскольку итерация фактически реализуется путем вызова следующего метода next() {
если (счет <= предел) {
возвращаться {
сделано: ложь,
значение: счетчик++
}
} еще {
return {готово: правда, значение: неопределенное }
}
},
возвращаться() {
console.log('Досрочное завершение итератора')
вернуть {готово: правда}
}
}} Test
const counter = new Counter(5)for (пусть i счетчика) {
если (я === 3) {
перерыв;
}
console.log(i)} 
Если итератор не закрыт, вы можете продолжить итерацию с того места, где остановились . Итераторы массива не могут быть закрыты.
const arr = [1, 2, 3, 4, 5]const iter = arr[Symbol.iterator]()iter.return = function () {
console.log('Досрочный выход из итератора')
возвращаться {
сделано: правда
}}for (const i of iter) {
консоль.log(я)
если (я === 2) {
перерыв
}}for (const i of iter) {
console.log(i)} 