Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. JavaScript
Code

Использование итераторов и генераторов в JavaScript для оптимизации кода

by
Difficulty:AdvancedLength:MediumLanguages:

Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)

Введение

Вам когда-нибудь нужно было перебирать список, но для выполнения операции потребовалось значительное количество времени? У вас когда-либо был сбой программы, потому что операция использовала слишком много памяти? Это случилось со мной, когда я попытался реализовать функцию, которая генерирует простые числа.

Создание простых чисел до миллиона заняло гораздо больше времени, чем мне хотелось бы. Но создание номеров до 10 миллионов было невозможно. Моя программа дала сбой или просто зависала. Я уже использовал решетку Эратосфена, которая должна быть более эффективной при создании простых чисел, чем метод грубой силы.

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

Скомпилированный язык может быстрее обрабатывать код. Но использование другого языка может оказаться непрактичным. Вы также можете попробовать использовать несколько потоков. Еще раз повторюсь, что это может быть непрактично, потому что ваш язык программирования должен был бы поддержать это.

К счастью, с JavaScript есть еще один вариант. Если у вас есть вычислительно интенсивная задача, вы можете использовать итераторы и генераторы, чтобы получить некоторую эффективность. Итераторы являются свойством некоторых коллекций JavaScript.

Итераторы повышают эффективность, позволяя вам потреблять элементы в списке по одному, как если бы они были потоком. Генераторы - это особый вид функции, которая может приостановить выполнение. Вызов генератора позволяет вам производить данные по одному куску за раз, без необходимости хранить его в списке в первую очередь.

Итераторы

Во-первых, давайте рассмотрим различные способы, которыми вы можете перемещаться по наборам в JavaScript. Цикл вида for (initial; condition; step) { ... } будет выполнять команды в своем теле определенное количество раз. Аналогично, цикл while будет выполнять команды в своем теле до тех пор, пока его условие будет истинным.

Вы можете использовать эти циклы для перемещения по списку, увеличивая индексную переменную на каждой итерации. Итерация - это выполнение тела цикла. Эти циклы не знают о структуре вашего списка. Они действуют как счетчики.

Циклы for/in и for/of предназначены для итерации по конкретным структурам данных. Итерация по структуре данных означает, что вы переходите через каждый из ее элементов. Цикл for/in выполняет итерацию по ключам в обычном JavaScript-объекте. A цикл for/of повторяется над значениями итерации. Что такое итерируемый? Проще говоря, итерабельным является объект с итератором. Примерами итераций являются массивы и множества. Итератор является свойством объекта, который предоставляет механизм для перемещения по объекту.

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

Вы получаете доступ к текущему элементу, вызывая метод итератора next. Метод next вернет значение текущего элемента и логическое значение, чтобы указать, когда вы достигли конца коллекции. Ниже приведен пример создания итератора из массива.

Вы также можете перебирать значения итератора с помощью цикла for/of. Используйте этот метод, когда знаете, что хотите получить доступ ко всем элементам объекта. Вот как вы бы использовали цикл для повторения в предыдущем списке:

Зачем использовать итератор? Использование итератора полезно, когда вычислительная стоимость обработки списка высока. Если у вас очень большой источник данных, это может вызвать проблемы в вашей программе, если вы попытаетесь выполнить итерацию по нему, потому что вся коллекция должна быть загружена.

С помощью итератора вы можете загружать данные по кускам. Это более эффективно, потому что вы управляете только частью списка, который вам нужен, без дополнительных затрат на обработку всего списка.

Примером может быть то, что вы загрузили данные из файла или базы данных и хотите постепенно отображать информацию на экране. Вы можете создать итератор из данных и настроить обработчик событий, чтобы захватить несколько элементов каждый раз, когда происходит событие. Это пример того, как может выглядеть такая реализация:

Генераторы

Если вы хотите создать коллекцию, вы можете сделать это с помощью генератора. Функция генератора может возвращать значения по одному за раз, приостанавливая выполнение на каждой итерации. Когда вы создаете экземпляр генератора, эти элементы могут быть доступны с помощью итератора. Это общий синтаксис для создания функции генератора:

* означает, что это функция генератора. Ключевое слово yield приостанавливает нашу функцию и обеспечивает состояние генератора в этот конкретный момент. Зачем вам использовать генератор? Вы бы использовали генератор, если хотите алгоритмически произвести значение в коллекции. Это особенно полезно, если у вас очень большая или бесконечная коллекция. Давайте посмотрим на пример, чтобы понять, как это нам помогает.

Предположим, у вас есть игра в онлайн-пул, которую вы создали, и вы хотите, чтобы игроки соответствовали игровым комнатам. Ваша цель состоит в том, чтобы сгенерировать все способы, которыми вы можете выбрать двух разных игроков из списка из 2000 игроков. Комбинации двух игроков, созданные из списка ['a', 'b', 'c', 'd'], будут ab, ac, ad, bc, bd, cd. Это решение с использованием вложенных циклов:

Теперь попробуйте выполнить функцию со списком из 2000 элементов. (Вы можете инициализировать свой список, используя цикл for, который добавляет числа от 1 до 2000 в массив). Что происходит сейчас, когда вы запускаете свой код?

Когда я запускаю код в онлайн-редакторе, происходит сбой веб-страницы. Когда я запускаю его в консоли в Chrome, я вижу, что вывод медленно печатается. Тем не менее, процессор моего компьютера начинает переходить в овердрайв, и мне нужно выйти из Chrome. Это переработанный код с использованием функции генератора:

Другим примером является то, что мы хотим генерировать числа в последовательности Фибоначчи до бесконечности. Вот одна из реализаций:

Как правило, бесконечный цикл приведет к сбою вашей программы. Функция fibGen способна работать вечно, потому что условие остановки отсутствует. Но поскольку это генератор, вы управляете каждым шагом.

Обзор

Итераторы и генераторы пригождаются, когда вы хотите постепенно обрабатывать коллекцию. Вы получаете эффективность, отслеживая состояние коллекции, а не все элементы коллекции. Элементы в коллекции оцениваются по одному, а оценка остальной коллекции откладывается.

Итераторы обеспечивают эффективный способ перемещения и управления большими списками. Генераторы обеспечивают эффективный способ создания списков. Вы должны попробовать эти методы, если в противном случае вы использовали бы сложный алгоритм или реализовали бы параллельное программирование для оптимизации вашего кода.

Если вы ищете дополнительные ресурсы для изучения или использования в своей работе, ознакомьтесь с тем, что у нас есть на рынке Envato.

Ресурсы

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.