В этой статье подробно описывается не особо известный функционал (среди начинающих программистов), то тем не менее очень нужный который был введен в ES2015: Итераторы.
Статья является свободным переводом статьи Kushan Joshi — How I learned to Stop Looping and Love the Iterator. В оригинальной статье итераторы сравниваются с обычным циклом for и описываются недостатки использования цикла for в сравнение с итераторами. Что на мой взгляд является спорным мнением и поэтому в переводе эта часть пропущена. Зато просто и подробно были описаны итераторы, что мне кажется может быть интересным. При чтение рекомендуется весь код из статьи продублировать в каком-нибудь онлайн редакторе типа https://codesandbox.io/.
Спонсор поста Честный рейтинг хостинг провайдеров по множеству параметров: отзывам клиентов, оценкам базовых параметров хостинга, тарифных предложений, качеству предоставляемых услуг. На данный момент 309 хостеров 1429 отзывов. Пример тематического рейтинга: лучшие хостинги для phpBB .
Iterables можно найти везде в Javascript, вы обязательно использовали их даже, если не знали об этом. Все, что имеет свойство Symbol.iterator, является итеративными объектами то есть iterables.
Давайте посмотрим на простейшую итерируемую строку!
str = 'hello world'; iterator = str[Symbol.iterator](); // StringIterator {} iterator.next(); // gives `h` ... ... iterator.next(); // gives `d` iterator.next(); // gives `undefined` as no more string left.
Тип строки String в javascript поставляется с протоколом итерации, что означает, что теперь мы можем сказать, что строки являются итеративными.
Эта тема достойна самой статьи, но вкратце Symbol решает проблему создания свойства в объекте, с которыми вы хотите быть уверенными в отсутствие конфликтов с каким-либо существующими свойствами.
По спецификации, в качестве ключей для свойств объекта могут использоваться только строки или символы (Symbol). Ни числа, ни логические значения не подходят, разрешены только эти два типа данных. И Symbol всегда представляет собой уникальный идентификатор, даже если создать множество символов с одинаковым описанием, это всё равно будут разные символы.
Так что больше не нужно использовать
@@@@@\_my_hidden_property\_
в ваших объекта!
Symbol.iterator — это глобально доступная константа, с помощью которой каждый может реализовывать итерационный протокол. Таким образом, вы можете использовать его, чтобы ваш собственный объект реализовал итерацию.
class Rand { [Symbol.iterator] () { let count = 0; return { next: () => ({ value: count++, done: count > 5 }) }; } } var rand = new Rand(); var iterator = rand[Symbol.iterator](); iterator.next();// {value: 0, done: false} iterator.next();// {value: 1, done: false} // .. iterator.next();// {value: 5, done: false} iterator.next();// {value: undefined, done: true}
Давайте подробно рассмотрим этот пример:
Повторяй за мной,
class Rand { [Symbol.iterator] () { // Rand имеет метод `Symbol.iterator`, потому это iterable! let count = 0; return { // Возвращает значение `iterator` next: () => ({ value: count++, done: count > 5 }) }; } }
var iterator = rand[Symbol.iterator](); // это iterator iterator.next(); // {value: 0, done: false} iterator.next(); // {value: 1, done: false} ... iterator.next(); // {value: 4, done: false} iterator.next(); // {value: undefined, done: true}
Вы получаете много суперспособностей бесплатно, если вы включаете итерацию в своем пользовательском объекте или используете любую из встроенных в Javascript итераций, такую как Array, string, Map или Set.
Помните класс Rand, который мы только что определили? Поскольку он является итеративным (iterable), он наследует суперсилу оператора spread.
var rand = new Rand(); var myArray = [...rand]; // [0, 1, 2, 3, 4] // string can also be used since it is an iterable [..."kushan"]; // ["k", "u", "s", "h", "a", "n"]
Примечание: Обратите внимание, мы не делали [… rand[Symbol.iterator]()], так как … ожидается iterable
, а не iterator
.
Array.from(rand); // [0, 1, 2, 3, 4] Array.from("kushan"); // ["k", "u", "s", "h", "a", "n"]
for of — это новый механизм циклов, представленный в ES2015, который понимает только iterables. Он автоматически вызывает Symbol.iterator, который хранит итератор за кулисами и вызывает .next. Он также останавливается, когда итератор возвращает {done: true}.
for(const v of rand) { console.log(v); } /*Output*/// 0 // 1 // .. // 4
В отличие от оператора spread, цикл for of может принимать как iterable, так и iterator.
var map = new Map([['a', 1], ['b', 2]]); map[Symbol.iterator];// map iterable так как он имеет ключ `Symbol.iterator` // `for of` понимает `iterable` for (const [key, val] of map) { console.log(key, val); // 'a', 1 } // `for of` так понимает iterators var iterator = map[Symbol.iterator](); // возвращает iterator for (const [key, val] of iterator) { console.log(key, val); // 'a', 1 } // .keys() часть `Map` api var keyIterator = map.keys(); // возвращает iterator for (const key of keyIterator) { console.log(key); // 'a' } // .values() часть `Map` api var valueIterator = map.values(); // возвращает iterator for (const val of valueIterator) { console.log(val); // 1' }
Это одна из моих любимых демонстраций суперсилы iterables. ES2015 представил destructuring assignment , которое построено на основе итерируемых элементов (iterables). Destruct понимает только iterables!
// array is iterable [a, b] = [10, 20]; // a=10, b=20 // наш класс rand :P [a, b, c] = rand; // a = 0, b = 1, c = 2 // вы даже можете так [a, ...b] = rand; // a = 0, b = [1, 2, 3, 4]
Пожалуйста, поделитесь любой другой суперсилой, которую вы знаете при использовании iterables. Я надеюсь, что эта статья поможет вам понять iterables и iterators.
Не забудьте проверить мои предыдущие статьи.
Если вы ❤️эту статью, пожалуйста, поделитесь этой статьей, чтобы ее … распространить (игра слов: spread the words).
Краткий перевод: https://vuejs.org/guide/components/v-model.html Основное использование v-model используется для реализации двусторонней привязки в компоненте. Начиная с Vue…
Сегодня мы рады объявить о выпуске Vue 3.4 «🏀 Slam Dunk»! Этот выпуск включает в…
Vue.js — это универсальный и адаптируемый фреймворк. Благодаря своей отличительной архитектуре и системе реактивности Vue…
Недавно, у меня истек сертификат и пришлось заказывать новый и затем устанавливать на хостинг с…
Каким бы ни было ваше мнение о JavaScript, но всем известно, что работа с датами…
Все, кто следит за последними событиями в мире адаптивного дизайна, согласятся, что введение контейнерных запросов…