Кратко
СкопированоIterator создаёт итератор только с теми значениями, которые удовлетворяют условию колбэк-функции. Фильтрация значений выполняется по мере необходимости (lazy evaluation). При каждом вызове метода next, итератор будет возвращать следующее подходящее значение исходного итератора, определённое с помощью колбэк-функции. О том, что такое итератор, можно прочитать в статье «Итератор».
Пример
СкопированоПредставим, что у нас есть итератор для массива чисел.
Необходимо получить только чётные значения:
// Итератор для массиваconst iterator = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].values()// Создаём итератор для получения чётных чиселconst evenIterator = iterator.filter(num => num % 2 === 0)// Получаем чётные значенияconsole.log(evenIterator.toArray())// [ 2, 4, 6, 8, 10 ]
// Итератор для массива
const iterator = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].values()
// Создаём итератор для получения чётных чисел
const evenIterator = iterator.filter(num => num % 2 === 0)
// Получаем чётные значения
console.log(evenIterator.toArray())
// [ 2, 4, 6, 8, 10 ]
Как пишется
СкопированоIterator принимает один обязательный аргумент — колбэк-функцию.
При вызове колбэк-функция получает аргументы:
- element — текущее значение итератора;
- index — индекс значения;
Функция выполняется для каждого значения, которое извлекается из итератора. Она вызывается не сразу для всех элементов, а только в случае запроса данных (например, при вызове .next или переборе в цикле for).
Если результат функции это false или другое falsy, то перебор итератора продолжится, пока не найдётся значение, для которого колбэк вернёт true или другое truthy значение.
Если попытаться выполнить Iterator без аргумента или передать не функцию, будет брошена ошибка Type.
Iterator возвращает новый итератор.
Как понять
СкопированоМетод Iterator можно сравнить с методом массива Array. Оба метода применяются для фильтрации значений с помощью колбэк-функции.
В отличие от массивов, итераторы используют «ленивые» вычисления (lazy evaluation). Это позволяет не перегружать память, избегать лишних операций, а главное — даёт возможность работать с большими или бесконечными потоками данных (лог-файлы, сенсоры, генераторы).
Рассмотрим, как можно выполнять фильтрацию данных полученных из генератора.
У нас есть функция-генератор пин-кодов:
function* pinGenerator(length = 8) { const charset = '01234567890123456789' while (true) { let id = ''; for (let i = 0; i < length; i++) { const random = Math.floor(Math.random() * charset.length); id += charset[random]; } yield id; }}
function* pinGenerator(length = 8) {
const charset = '01234567890123456789'
while (true) {
let id = '';
for (let i = 0; i < length; i++) {
const random = Math.floor(Math.random() * charset.length);
id += charset[random];
}
yield id;
}
}
При вызове функция вернёт итератор. Создадим итератор пин-кодов из 4-х цифр и получим несколько значений:
const pins = pinGenerator(4)console.log(pins.next().value)// 6147console.log(pins.next().value)// 1848
const pins = pinGenerator(4)
console.log(pins.next().value)
// 6147
console.log(pins.next().value)
// 1848
Допустим, что для удобства ввода в приложении, необходимо получать пин-коды, в которых одна из цифр повторятся дважды.
Применим фильтрацию к исходному итератору и создадим итератор отфильтрованных значений. Колбэк-функция будет проверять сколько уникальных цифр содержит строка. Если одна из цифр повторяется дважды, размер Set-коллекции будет равен 3:
// Создаём итератор для получения пин-кодов с повторяющейся цифройconst easyPins = pins.filter(pin => { const digits = pin.split('') const uniqueDigits = new Set(digits) // Если в строке ровно 3 уникальные цифры, // значит одна цифра повторяется дважды return uniqueDigits.size === 3})console.log(easyPins.next().value)// 3319console.log(easyPins.next().value)// 4008console.log(easyPins.next().value)// 0226
// Создаём итератор для получения пин-кодов с повторяющейся цифрой
const easyPins = pins.filter(pin => {
const digits = pin.split('')
const uniqueDigits = new Set(digits)
// Если в строке ровно 3 уникальные цифры,
// значит одна цифра повторяется дважды
return uniqueDigits.size === 3
})
console.log(easyPins.next().value)
// 3319
console.log(easyPins.next().value)
// 4008
console.log(easyPins.next().value)
// 0226
Оба итератора «бесконечны», так как не имеют конечного состояния ({ done).
Фильтрация работает, потому что колбэк-функция начинает выполняться только при запросе отфильтрованных значений и не вызывается для следующих значений итератора после получения истинного (truthy) значения.
Как и другие методы доступные через Iterator, filter выполняет для исходного итератора роль обёртки (wrapper), добавляя логику фильтрации.
Итератор, созданный методом Iterator, использует исходный итератор как источник данных и разделяет с ним состояние (указатель на текущее значение). Если вызвать next на одном из итераторов, указатель сдвинется для обоих — как для исходного, так и для отфильтрованного.
Рассмотрим связь итераторов на примере получения чётных значений:
// Итератор для массиваconst iterator = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].values()// Создаём итератор для получения чётных чиселconst evenIterator = iterator.filter(num => num % 2 === 0)// evenIterator выполняет колбэк-функцию для значений 1 и 2// Получаем первое чётное значениеconsole.log(evenIterator.next().value)// 2// Следующее доступное значение для обоих итераторов — 3// Получаем два значения исходного итератора: 3 и 4console.log(iterator.next().value)console.log(iterator.next().value)// 3// 4// Следующее доступное значение для обоих итераторов — 5// evenIterator выполняет колбэк-функцию для значений 5 и 6.// Получаем следующее чётное значениеconsole.log(evenIterator.next().value)// 6
// Итератор для массива
const iterator = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].values()
// Создаём итератор для получения чётных чисел
const evenIterator = iterator.filter(num => num % 2 === 0)
// evenIterator выполняет колбэк-функцию для значений 1 и 2
// Получаем первое чётное значение
console.log(evenIterator.next().value)
// 2
// Следующее доступное значение для обоих итераторов — 3
// Получаем два значения исходного итератора: 3 и 4
console.log(iterator.next().value)
console.log(iterator.next().value)
// 3
// 4
// Следующее доступное значение для обоих итераторов — 5
// evenIterator выполняет колбэк-функцию для значений 5 и 6.
// Получаем следующее чётное значение
console.log(evenIterator.next().value)
// 6
- Chrome 122, поддерживается
- Edge 122, поддерживается
- Firefox 131, поддерживается
- Safari 18.4, поддерживается