ru:https://highload.today/blogs/mozhno-vse-i-po-svoim-pravilam-kak-rabotaet-iteratsiya-v-javascript/ ua:https://highload.today/uk/blogs/mozhna-vse-i-za-svoyimi-pravilami-yak-pratsyuye-iteratsiya-v-javascript/
logo
Back-end      11/08/2022

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

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

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

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

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

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

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

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

  • Перечисляемые свойства enumerable properties — одно из трех свойств (configurable, enumerable, writable), имеющихся в объекте. Относительно enumerable, то она отвечает за то, можно ли вернуть свойство в цикле for...in.

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

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

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

Онлайн-курс "Нотації BPMN" від Laba.
Опануйте мову BPMN для візуалізації бізнес-процесів, щоб впорядкувати хаос у них.Після курсу ви точно знатимете, що саме обрати для розв’язання завдань вашого бізнесу.
Дізнатись більше

Сначала цикл 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 создан для асинхронной обработки (изменения) больших массивов данных.

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

Онлайн-курс "Маркетингова аналітика" від Laba.
Опануйте інструменти для дослідження ринку й аудиторії та проведення тестувань.Дізнайтесь, як оптимізувати поточні рекламні кампанії та будувати форкасти наступних.
Детальніше про курс

Класс 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, а просто используем надежный способ обработки данных.


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

Бізнес англійська від Englishdom.
Тут навчають за методикою Кембриджу, завдяки якій англійську вивчили понад 1 мільярд людей. Саме вона використовується в найкращих навчальних закладах світу, і саме за нею створені курси.
Інформація про курс

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

Онлайн курс UI/UX Design Pro від Ithillel.
Навчіться проєктувати інтерфейси з урахуванням поведінки користувачів, розв'язувати їх проблеми через Customer Journey Mapping, створювати дизайн-системи і проводити дослідження юзабіліті, включаючи проєктування мобільних додатків для Android та iOS і розробку UX/UI на основі даних!
Дізнатися більше

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

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

PHP Developer в ScrumLaunch
Всего просмотровВсего просмотров
2434
#1
Всего просмотровВсего просмотров
2434
Founder at Shallwe, Python Software Engineer (Django/React)
Всего просмотровВсего просмотров
113
#2
Всего просмотровВсего просмотров
113
Career Consultant в GoIT
Всего просмотровВсего просмотров
95
#3
Всего просмотровВсего просмотров
95
CEO & Founder в Trustee
Всего просмотровВсего просмотров
94
#4
Всего просмотровВсего просмотров
94
Рейтинг блогеров

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

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

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