UA RU
logo
Back-end      11/08/2022

Можно все, и по своим правилам: как работает итерация в JavaScript

Владислав Хирса BLOG

Senior Backend Developer | Node.js | NestJS | Express.js | SQL | NoSQL | AWS

Привет всем. Меня зовут Владислав Хирса, я — Software Engineer в Grid Dynamics. В этой статье я расскажу вам много полезного об итерации в JavaScript.

Онлайн-курс "Golang для розробників" від robot_dreams.
Вивчіть мову Golang від Google, щоб створювати продуктивний і надійний бекенд, опанувати паралелізм та перейти до високооплачуваної ніші розробки. .
Детальніше про курс

Мы все используем итерацию для перебора массивов и объектов разных размеров и разных задач. Но знаем ли мы, как это работает? Как мы можем изменить поведение итерации над нашими данными и в каких случаях это может потребоваться?

Если вам интересны ответы на эти вопросы, то этот материал точно для вас.

Вспомним термины

Для лучшего понимания вспомним несколько значений, а именно:

  • Перечисляемые свойства enumerable properties — одно из трех свойств (configurable, enumerable, writable), имеющихся в объекте. Относительно enumerable, то она отвечает за то, можно ли вернуть свойство в цикле for...in.
  • Онлайн-курс "Golang для розробників" від robot_dreams.
    Вивчіть мову Golang від Google, щоб створювати продуктивний і надійний бекенд, опанувати паралелізм та перейти до високооплачуваної ніші розробки. .
    Детальніше про курс

Например, так:

Object.prototype.getType = function() {
  return this.type;
};
const object = {
  language: 'JavaScript',
  type: 'Lesson'
};
for (const key in object) {
  console.log(key); // JavaScript, Lesson, getType;
};
  • Итерированный объект и terable object — это объект, построенный по определенному паттерну и имеющий типичное итерационное поведение. Он итерируется с помощью spread syntax [...], for...of и for await...of. И в этой статье мы поговорим именно о нем.
  • Протокол итерации iterator protocol это протокол, с помощью которого мы можем создать собственные правила, по которым будет итерироваться наш объект. Если подробнее, то итерировать мы сможем такие типы данных, как string, array, object.

Главные правила iterator protocol это:

  1. У нас должен быть метод next().
  2. Онлайн-курс повного дня Front-end developer від Mate academy.
    Цей курс ідеальний для новачків - 85% наших студентів не мали попереднього досвіду. Гарантованне працевлаштування: 3 500 випускників вже отримало роботу. .
    Отримати знижку на курс
  3. Метод next() должен обязательно возвращать объект типа iterable object. Он содержит ключи value, которые могут иметь любое значение, и done, который может быть true или false.
  4. Когда итерация завершилась, нужно обязательно вернуть объект { done: true }, ведь только после этого наша итерация закончится.
  5. Если done не будет возвращен или done будет иметь какое-либо негативное значение, такое как undefined, null и другие, то наша итерация будет бесконечной.

Создание итеративного поведения

Для создания итеративного поведения мы будем использовать следующие подходы:

  • Symbol.iterator с методом next();
  • Symbol.iterator с генератором;
  • Symbol.asyncIterator с генератором.

Так что по порядку, и начнем мы с Symbol.iterator с методом next().

var array = [10, 20, 30, 40, 50];
array[Symbol.iterator] = function () {
  let i = 0;
  return {
    next() {
      i++
      return (i <= 5)
        ? { value: i, done }
        : { done: true }
    }
  }
};
for (const el of array) {
  console.log(el) // 1, 2, 3, 4, 5
};

Как это работает?

Курс Java developer від Mate academy.
Вивчайте Java та отримайте можливість працювати майже в будь-якій галузі: її використовують від фінансової сфери до аграрної. Працевлаштування гарантуємо!
Отримати знижку на курс

Сначала цикл for...of ищет в нашем объекте или среди тех, от которых он наследуется в prototype, есть ли у него Symbol.iterator. Если нет — то будет вызвана автоматическая ошибка, а если да — тогда он вызывает функцию, функция возвращает наш объект с методом next(), где и есть вся наша основная логика, и самое главное, что при каждой итерации цикла используется метод next(), который и возвращает значение по нашим условиям.

Symbol.iterator з генератором

С Symbol.iterator уже ознакомились, а как насчет генераторов?

Генератор, если коротко, то это способ создания того же iterable object для итерации по iterator protocol, то есть у него тоже есть метод next() и он итерируется циклом for...of, только синтаксис другой, и использовать его в некоторых случаях удобнее:

var it = {};
it[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};
it.type = 'Lesson';
console.log(it); // { type: "Lesson", Symbol(Symbol.iterator): * Symbol.iterator() }
console.log([...it]); // [1, 2, 3]

В этой части мы изменили поведение объекта и дали ему возможность быть итерированным. Без Symbol.iterator была бы ошибка такого типа — Uncaught TypeError: it is not iterable при попытке итерировать объект. Так же как мы видим, что к итерационным данным мы не имеем доступа напрямую, а с Symbol.iterator нет доступа к значениям объекта. Это очень удобно, и нет никаких мутаций данных.

Symbol.asyncIterator з генератором

Очень интересный метод обработки данных, с помощью которого мы можем асинхронно обрабатывать данные, разбивать тяжелые и длительные операции, которые не перегружают и не блокируют нашу систему. Так что хочу поделиться с вами, возможно, немного сложным, но полезным примером использования. Для удобства в этом примере мы используем типы.

Файл async-iterator.ts:

import { AsyncLimitIteratorParametersType } from './types';
export default class Iterator {
  public static generateAsyncLimitIterator(
    data: AsyncLimitIteratorParametersType
  ) {
    const {
      from,
      to,
      limit,
      asyncFunction,
      asyncFunctionParams
   } = data;
    return {
      async *[Symbol.asyncIterator]() {
        for (let now = from; now < to; now += limit) {
          yield await asyncFunction(
            asyncFunctionParams,
            { from, to, limit, now }
          );
        }
      }
    }
  }
};

Файл types.d.ts:

export type AsyncLimitIteratorParametersType = {
  from: number;
  to: number;
  limit: number;
  asyncFunction: Function;
  asyncFunctionParams: any;
}
export type IterationDataType = {
  from: number;
  to: number;
  limit: number;
  now: number;
};

Класс Iterator создан для асинхронной обработки (изменения) больших массивов данных.

Так что разберем, как его можно использовать и в чем его преимущества.

Курс Project Manager від Powercode academy.
Онлайн-курс Project Manager. З нуля за 3,5 місяці до нової позиції Без знання коду, англійської та стресу.
Зарееструватися

Класс Iterator

Итак, класс Iterator. У него есть один статический метод generateAsyncLimitIterator, к которому мы имеем доступ, не используя оператор new, метод generateAsyncLimitIterator принимает параметры:

  • from — из какого индекса изменять массив;
  • to — по какой позиции по индексу изменять массив;
  • limit — сколько элементов за одну итерацию захватить и пройти;
  • asyncFunction — функция, в которой выполняются основные действия.

Например, запрос на базу данных для изменения объекта пользователей. asyncFunctionParams параметры, принимаемые функцией asyncFunction.

Пример применения:

const iteratorParams = {
  from: 0,
  to: 1000,
  limit: 10,
  asyncFunction: changeUsers,
  asyncFunctionParams: params
};
const iterateObj = Iterator.generateAsyncLimitIterator(iteratorParams);
for await (let value of iterateObj) {
  //
}

После того, как мы создали асинхронный итератор, мы просто используем его в асинхронном цикле и не беспокоимся о переполненном стеке вызовов и о том, что заблокирован Event Loop, а просто используем надежный способ обработки данных.


На этом все! Надеюсь, что было полезно. Желаю успехов и продуктивного кодинга 😉

Практичний інтенсивний курс з дизайну - Design Booster від Powercode academy.
Навчіться дизайну з нуля за 3 місяці і заробляйте перші $1000, навіть якщо ви не маєте креативного мислення, смаку або вміння малювати. Отримайте практичні навички, необхідні для успішної кар'єри в дизайні.
Зарееструватися

If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.

Онлайн-курс "HR-менеджер" від Laba.
За 10 тижнів у інтерактивній формі навчання під менторством exHRD у WorkUA ви отримаєте практичні навички й основні інструменти для старту кар’єри в HR. А також можливість стажування у Laba. .
Детальніше про курс

Этот материал – не редакционный, это – личное мнение его автора. Редакция может не разделять это мнение.

Топ-5 самых популярных блогеров сентября

Всего просмотровВсего просмотров
36
#1
Всего просмотровВсего просмотров
36
Всего просмотровВсего просмотров
29
#2
Всего просмотровВсего просмотров
29
Всего просмотровВсего просмотров
23
#3
Всего просмотровВсего просмотров
23
Career Consultant в GoIT
Всего просмотровВсего просмотров
21
#4
Всего просмотровВсего просмотров
21
Всего просмотровВсего просмотров
18
#5
Всего просмотровВсего просмотров
18
Рейтинг блогеров
Онлайн-курс Frontend-разробник від Powercode academy.
Курс на якому ти напишеш свій чистий код на JavaScript, попрацюєш із різними видами верстки, а також адаптаціями проектів під будь-які екрани. .
Зарееструватися

Самые обсуждаемые статьи

Топ текстов

Ваша жалоба отправлена модератору

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: