Кратко
СкопированоИтератор — это объект, который умеет обращаться к элементам коллекции по одному за раз, при этом отслеживая своё текущее положение внутри этой последовательности.
Иными словами итератор — механизм, который позволяет перемещаться (итерироваться) по элементам коллекции в определённом порядке и делает их доступными.
Как понять
СкопированоИтератор в JavaScript — объект, возвращающий следующий элемент последовательности через метод next. Этот метод возвращает объект с двумя свойствами:
value— значение текущего элемента коллекции.done— индикатор, указывающий, есть ли ещё в коллекции значения, доступные для перебора.
function makeIterator(array) { let nextIndex = 0 return { next: function () { if (nextIndex < array.length) { const result = { value: array[nextIndex], done: false } nextIndex++ return result } else { return { done: true } } } }}
function makeIterator(array) {
let nextIndex = 0
return {
next: function () {
if (nextIndex < array.length) {
const result = { value: array[nextIndex], done: false }
nextIndex++
return result
} else {
return { done: true }
}
}
}
}
После создания, объект-итератор можно использовать явно с помощью вызова метода next:
let iterator = makeIterator(['Hello', 'world'])console.log(iterator.next().value)// 'Hello'console.log(iterator.next().value)// 'world'console.log(iterator.next().done)// true
let iterator = makeIterator(['Hello', 'world'])
console.log(iterator.next().value)
// 'Hello'
console.log(iterator.next().value)
// 'world'
console.log(iterator.next().done)
// true
Как только метод next завершает перебор, возвращается { done. Это сигнал, что итерирование завершено.
Зачем это нужно
СкопированоПрактически везде, где нужен перебор, его реализуют через итераторы. Это включает в себя не только строки и массивы, но и другие структуры данных. В современный JavaScript добавлена новая концепция «итерируемых» (iterable) объектов, например, Map, представленный в ES6. Это позволяет перебрать итерируемый объект в цикле for:
for (let value of ['a', 'b', 'c']) { console.log(value) // a // b // c}
for (let value of ['a', 'b', 'c']) {
console.log(value)
// a
// b
// c
}
Предположим, у нас есть объект person, который представляет набор данных:
const person = { name: 'Mark', age: 30, gender: 'male', interests: ['music', 'fishing'],}
const person = {
name: 'Mark',
age: 30,
gender: 'male',
interests: ['music', 'fishing'],
}
Чтобы сделать такой объект итерируемым и позволить for работать с ним, определим в нём Symbol:
person[Symbol.iterator] = function () { const properties = Object.keys(this) let count = 0 return { next() { if (count < properties.length) { const key = properties[count] let result = { done: false, value: person[key] } count++ return result } else { return { done: true } } }, }}
person[Symbol.iterator] = function () {
const properties = Object.keys(this)
let count = 0
return {
next() {
if (count < properties.length) {
const key = properties[count]
let result = { done: false, value: person[key] }
count++
return result
} else {
return { done: true }
}
},
}
}
Убедимся, что объект person действительно итерируется:
for (let x of person) { console.log(x) // Mark, 30, male, ['music', 'fishing']}
for (let x of person) {
console.log(x)
// Mark, 30, male, ['music', 'fishing']
}
Встроенные итераторы
СкопированоВ некоторых случаях интерфейс итератора вызывается по умолчанию. Такие объекты, как String, Array, Map и Set итерируемые, потому что их прототипы содержат Symbol.
Где ещё встречается итератор
СкопированоДеструктуризация
СкопированоПри деструктуризации итератор используется для доступа к элементам коллекции:
const [a, b] = new Set(['a', 'b', 'c'])// a// b
const [a, b] = new Set(['a', 'b', 'c'])
// a
// b
Array.from()
СкопированоArray позволяет конвертировать итерируемый объект в массив:
const arr = Array.from(new Set(['a', 'b', 'c']))// ['a', 'b', 'c']
const arr = Array.from(new Set(['a', 'b', 'c']))
// ['a', 'b', 'c']
Спред-оператор
СкопированоСпред-оператор также вызывает интерфейс итератора по умолчанию:
const arr = [...new Set(['a', 'b', 'c'])]// ['a', 'b', 'c']
const arr = [...new Set(['a', 'b', 'c'])]
// ['a', 'b', 'c']
Map, Set
СкопированоКонструкторы Map и Set преобразуют итерируемые значения в Map и Set соответственно:
const map = new Map([ ['uno', 'one'], ['dos', 'two'],])map.get('uno')// onemap.get('dos')// twoconst set = new Set(['red', 'green', 'blue'])set.has('red')// trueset.has('yellow')// false
const map = new Map([
['uno', 'one'],
['dos', 'two'],
])
map.get('uno')
// one
map.get('dos')
// two
const set = new Set(['red', 'green', 'blue'])
set.has('red')
// true
set.has('yellow')
// false