Демістифікація взаємодіючих та ітераторів ES6

ES6 представляє новий спосіб взаємодії зі структурами даних JavaScript - ітерацію . Давайте демістифікуємо це.

Існує 2 основних поняття:

  • Ітерабельний - описується структурою даних, яка надає спосіб виставити свої дані широкому загалу. Це робиться шляхом реалізації методу, ключем якого є Symbol.iterator. Symbol.iteratorє фабрикою ітераторів.
  • Ітератор - описується структурою, що містить вказівник на наступний елемент в ітерації.

Протокол

Ітератор, і ітератор дотримуються протоколу, який дозволяє об'єктам бути ітерабельними:

  • Interable повинен бути об'єктом з функцією ітератора , чий ключ Symbol.iterator.
  • Итератор повинен бути об'єктом функції з ім'ям , nextякий повертає об'єкт з ключами: value- поточний пункт в ітерації; і done- true, якщо ітерація закінчилася, false в іншому випадку.

Ітерабельність

Сумісність слідує ідеї джерел даних та споживачів даних :

  • джерела даних - це місце, звідки споживачі даних отримують свої дані. Наприклад, наприклад, Arrayтака як [1,2,3]структура джерела даних, яка містить дані, за допомогою яких споживач даних буде повторювати (наприклад 1, 2, and 3). Більше прикладів String, Mapsта Sets.
  • споживачі даних - це те, що споживають дані з джерел даних. Наприклад, for-ofцикл - це споживач даних, який може перебирати Arrayджерело даних. Інші приклади - це spread operatorі Array.from.

Щоб структура була джерелом даних , вона повинна дозволити і сказати, як слід використовувати її дані. Це робиться за допомогою ітераторів . Отже, джерело даних має слідувати описаному вище протоколу ітераторів.

Однак не практично для кожного споживача даних підтримувати всі джерела даних , тим більше, що JavaScript дозволяє нам створювати власні джерела даних. Тож ES6 представляє інтерфейс Iterable .

Споживачі даних споживають дані з джерел даних через ітерабелі .

На практиці

Давайте подивимося, як це працює на визначеному джерелі даних - Array.

Джерела даних, що підлягають ітерації

Ми використаємо for-ofдля вивчення деяких джерел даних, що реалізують ітерабельний протокол .

Рівнинні об’єкти

На цьому етапі потрібно сказати, що звичайні об’єкти не піддаються ітерації. Аксель Раушмайер чудово справляється з поясненням, чому саме на дослідженні ES6.

Коротке пояснення полягає в тому, що ми можемо переглядати об'єкти JavaScript на двох різних рівнях:

  • програмний рівень - що означає перебір властивостей об'єкта, що представляють його структуру. Наприклад, Array.prototype.lengthде lengthпов'язано зі структурою об'єкта, а не з даними.
  • рівень даних - означає перегляд структури даних та вилучення її даних. Наприклад, для нашого Arrayприкладу це означало б перебір даних масиву. Якщо array = [1,2,3,4], перебирайте значення 1, 2, 3 and 4.
Однак введення концепції ітерації в звичайні об'єкти означає змішування програм та структур даних - Axel

Проблема звичайних об’єктів полягає в здатності всіх створювати власні об’єкти.

У нашому прикладі Гюго, як JavaScript розрізнятиме рівень даних, тобто Hugo.fullName, і рівень програми, тобто Hugo.toString()?

Хоча можна розрізнити два рівні ітерації на чітко визначених структурах, наприклад Arrays, це неможливо зробити для будь-якого об'єкта.

Саме тому ми отримуємо ітерацію безкоштовно на Array(також в String, Mapі Set) , але не на простих об'єктах.

Однак ми можемо реалізувати власні ітерабелі.

Впровадити Iterables

Ми можемо створити власні ітерабелі, хоча зазвичай для цього використовуємо генератори.

Для того, щоб створити свій власний ітерабель, нам потрібно дотримуватися протоколу ітерацій, який говорить:

  • Об'єкт стає ітерабельним, якщо він реалізує функцію, ключем якої є Symbol.iteratorі повертає iterator.
  • Сам iteratorпо собі є об'єктом з функцією, що викликається nextвсередині нього. nextповинен повернути об'єкт з двома ключами valueі done. valueмістить наступний елемент ітерації та doneпрапор, який повідомляє, що ітерація закінчилася.

Приклад

Наша ітераційна реалізація дуже проста. Ми дотримувались ітерабельного протоколу, і на кожній ітерації for-ofцикл запитуватиме у ітератора nextелемент.

Наш ітератор повернеться nextдо об’єкта, що містить таке за допомогою ітерації:

Зверніть увагу , що ми міняємо порядок наших властивостей nextі doneдля зручності. Маючи nextперше, це порушить реалізацію, оскільки ми спочатку виведемо елемент, а потім підрахуємо елементи.

Корисно знати, що doneце falseза замовчуванням, а це означає, що ми можемо ігнорувати його, коли це так. Те саме стосується і того, valueколи doneє true.

Це ми побачимо за хвилину.

Ітератор як ітерабель

Ми могли б створити наш ітератор як ітерабель.

Зверніть увагу, що за цією схемою слідують вбудовані ітератори ES6.

Чому це корисно?

Хоча це for-ofпрацює лише з ітераторами, а не з ітераторами, але те саме означає, що ми можемо призупинити виконання for-ofта продовження післямов.

Повернення і кидок

Є два необов’язкові методи ітераторів, які ми ще не досліджували:

Повернення

returnдає можливість ітератору прибирати будинок, коли він несподівано розбивається. Коли ми звертаємось returnдо ітератора, ми вказуємо, що більше не плануємо дзвонити next.

Кинути

throwзастосовується лише до генераторів. Це ми побачимо, коли пограємо з генераторами.

Висновок

ES6 пропонує ітерацію як новий спосіб перебору структур даних JavaScript.

Щоб ітерація була можливою, існують виробники даних , які містять дані, та споживачі даних, які беруть ці дані.

Для того, щоб ця комбінація працювала плавно, ітерація визначається протоколом, який говорить:

  • An iterable- це об'єкт, який реалізує функцію, ключ якої Symbol.iteratorі повертає iterator.
  • An iterator- це об'єкт, функція якого викликається nextвсередині нього. nextє об'єктом з двома ключами valueі done. valueмістить наступний елемент ітерації та doneпрапор, який повідомляє, що ітерація закінчилася.

Звичайні об'єкти не є, iterableоскільки немає простого способу розрізнити ітерацію програми та рівня даних.

Ось чому ES6 пропонує спосіб побудови власних ітераторів, дотримуючись iteratorпротоколу.

Завдяки ?

  • Аксель Раушмайер за його «Дослідження ES6 - ітерація»
  • Ніколас Беваква за його ітератори PonyFoo - ES6 у глибині
  • Усім шанувальникам Сімпсонів

Обов’язково перегляньте інші мої статті про ES6

Давайте дослідимо генератори ES6

Генератори - це реалізація ітерацій. medium.freecodecamp.com