Цикл по структурам данных в JavaScript ES6

Сегодня я собираюсь более подробно рассмотреть новые способы навигации по структурам данных в 6-м издании стандарта ECMAScript, обычно называемом ES6. Среди всех обновлений и синтаксического сахара, добавленных в JavaScript в 2015 году, теперь также есть поддержка итераторов и повторяемых объектов. Они не только позволяют сократить количество кода при итерации по массивам и строкам, но и поддерживают новые коллекции, такие как карты и наборы, а также создание для них настраиваемых объектов и итераторов. Вы можете думать об этом как о подобном (но не о том же) цикле, который происходит в цикле for-in на стероидах.

Хорошо, вам может быть интересно, что такое итераторы и итерируемые объекты? Итерируемый - это последовательная структура данных, которую можно повторять. Итерируемые объекты также могут иметь собственный метод доступа, определяющий его итератор. Это позволяет сделать итерируемые объекты общедоступными. Итератор похож на указатель, который определенным образом перемещается по коллекции. Как мы чуть позже выясним, эти новые настраиваемые итераторы в ES6 могут обрабатывать не только простой массив.

Это много жаргона, который я разберу через несколько минут на примере. Но для начала давайте взглянем на использование итераторов ES6 по умолчанию в цикле for-of.

Цикл for-of

В ES5 и ранее мы использовали циклы for и while для перебора массивов или строк. Теперь, с ES6, мы можем перемещаться по массиву или строке, не задавая параметры для этих циклов. Цикл for-of по умолчанию знает, как последовательно перебирать эти типы данных:

В этих примерах массив и строка теперь являются структурами данных итерация, и когда мы используем цикл for-of для итерации по коллекции, мы объявляем имя переменной для итератора для использования -, например x или char.

Добавление карты и набора

В дополнение к быстрой навигации по массивам и строкам, цикл for-of также можно использовать на картах и ​​наборах - оба из них теперь также легко доступны в ES6. Обе структуры данных могут быть инициализированы с помощью ключевого слова new (следуя псевдоклассическому шаблону создания экземпляров).

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

Итерировать или… перечислить?

Возможно, вы заметили, что объекты здесь не отображаются, хотя в начале я упоминал итерируемые объекты. Причина в том, что стандартные объекты JavaScript не являются итерируемыми структурами данных, а являются перечисляемыми - у них нет внутреннего порядка, который массивы, строки, а теперь и карты и наборы. Объекты содержат неупорядоченный набор пар ключ-значение. Однако мы все еще можем использовать цикл for-in для перечисления ключей и / или значений объекта. Но, как мы увидим, мы также можем создавать собственные итерируемые объекты и итераторы в ES6.

Symbol.iterator

В то время как циклы for-of по умолчанию доступны для массивов, строк, наборов и карт, ES6 также позволяет настраивать итерации и итераторы с использованием Symbol.iterator. Символ - это новый примитивный тип данных в ES6. Он определяет итераторы и итерационные процессы для любой коллекции любого размера и сложности. Он работает как метод объекта, и поэтому Symbol.iterator хранится как ключ для настраиваемого итеративного объекта. Его также можно использовать для определения шаблона итераций, который будет использоваться в предоставленных структурах данных JavaScript. Symbol.iterator - это также код, который выполняется за кулисами, чтобы заставить цикл for-of работать по умолчанию для вышеупомянутых структур данных.

Чтобы упростить задачу и понять, как работает этот символ, давайте создадим итератор, который будет перебирать массивы в обратном порядке. В этом примере мы не будем добавлять символ в качестве ключа к настраиваемому объекту, потому что он будет использоваться в массивах, поэтому этот итератор является автономным. Но структура Symbol.iterator была бы аналогичной, если бы она была ключом в настраиваемом повторяемом объекте. Сначала мы создадим обратный итератор:

Подобно циклу for, мы собираемся отслеживать индекс и начинать с конца коллекции (строка 3). Symbol.iterator использует клавишу next, чтобы определить, когда и как выполнять итерацию (строка 5). Все итераторы обращаются к этому следующему методу, чтобы определить его шаблон итерации. В нашем обратном итераторе каждый раз, когда вызывается next(), он будет проходить в обратном направлении по структуре (строка 6), останавливаясь, когда i меньше нуля (строка 7).

Теперь мы можем вызвать обратный вызов в цикле for-of и voilà! Итерация в обратном порядке по массиву:

Обратите внимание, что в приведенном выше примере итераторы не ограничиваются циклами for-of: они также могут использоваться с операторами распространения в ES6. В строке 8 оператор распространения применяет итератор reverse к нашему массиву, распределяя результат.

В заключение мы рассмотрели некоторые из быстрых способов, которыми ES6 позволяет нам перебирать целый ряд типов данных с помощью цикла for-of - от массивов до строк и новых доступных наборов и карт. И мы намочили пальцы, рассказывая о создании собственных итераторов с Symbol.iterator. Очевидно, что знакомство с циклами for-of, итераторами и итерациями в JavaScript ES6 не только сократит наш код, но и откроет совершенно другое измерение пользовательских структур данных и инструментов, которые мы можем использовать для навигации по ним и доступа к информации, которую они хранить.

Ссылки - углубитесь в итерацию ES6: