Понимание того, как for-of работает за кулисами, чтобы использовать весь его потенциал и перестать делать неверные прогнозы при его использовании.

Отказ от ответственности: это не одна из тех статей, в которых повторяются функции ES6 / ESnext только для того, чтобы вы знали, как они выглядят, но здесь мы подробно рассмотрим, что происходит за кулисами, когда вы используете for-of, как предусмотрено ES6 (ECMASCRIPT 2015)

ES6 предоставляет синтаксис for-of ,, который является довольно удобным способом перебора значений в массиве (в основном) или так называемых итераций - подробнее об этом скоро.

с good-ol для цикла было бы совсем иначе

сравнивая фрагменты i и ii, вы подтверждаете, что for-of выполняет работу более интуитивно, не открывая индекс. Хотя это совершенно гладко и просто, нужно еще кое-что понять. Теперь давайте заглянем за кулисы, чтобы увидеть, как работает for-of.

Фактическое поведение

for-of запрашивает объект-итератор (из внутренней функции по умолчанию, известной как @@ iterator) вещей, которые нужно повторить. , цикл затем перебирает последовательное возвращаемое значение при вызове метода итераторов .next(), один раз для каждой итерации цикла

Не беспокойтесь, если вы этого не совсем понимаете!

Такие типы, как Strings, Array, TypedArray, Maps и Set, реализуют метод @@ iterator. Это означает, что объект (или один из объектов в цепочке прототипов) должен иметь свойство с ключом @@ итератора, доступным через константу Symbol.iterator.

Итератор

Итератор - это объект, реализующий .next() метод. Значение next - это функция с нулевым аргументом, которая возвращает объект как минимум с двумя свойствами done и value.

done это логическое (_7 _ / _ 8_) значение, которое указывает, должен ли for-of завершать итерацию или нет.

value - это значение, которое должно возвращаться на каждой итерации функцией for-of..

{  
 next: function(){
   return{value: 10 , done:false}
 }
}

Итерабельный

Как правило, любой объект, реализующий метод @@ iterator, является итерируемым. Следовательно, Строки, Array, TypedArray, Maps и Set являются итеративными. По сути, объект должен иметь свойство с ключом @@ iterator, который реализуется через константу Symbol.iterator .

Обычный объект по умолчанию не поддерживает итерацию.

const foo = {name: "Agboola Jude", password:"*****"}
for(const value of foo){//..}
Uncaught TypeError: foo is not iterable
   

Поскольку for-of принимает итератор, вы получите TypeError, который будет отброшен на вас, если foo не является итератором. Обычные объекты не являются итеративными, поэтому вы должны реализовать метод @@ iterator (мы рассмотрим это вскоре), чтобы заставить их работать в цикле for-of и некоторые другие синтаксисы, ожидающие итерабельности , что выходит за рамки этой статьи. Попытайтесь понять это, и вы перестанете использовать их неправильно.

Доступ к методу итератора вручную

Ранее я упоминал, что Strings, Array, TypedArray, Maps и Set реализуют метод @@ iterator . Он реализован по умолчанию для любого из этих типов (для каждого типа совершенно разные реализации).

Теперь позвольте получить доступ к методу итератора для типа String, как обычно делает for-of за кулисами.

Исходя из вышесказанного, я рад сообщить вам, что на самом деле for-of делает за кулисами. Он получает метод объекта и вызывает к нему .next().

Примечание. Метод @@ iterator фактически возвращает итератор, обратите внимание на итератор!

Пользовательский метод @@ iterator (создание итерации обычного объекта)

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

Во фрагменте iv ниже мы определяем объект и делаем его итеративным, реализуя метод @@ iterator. это делается путем добавления ключа @@ iterator к объекту, который доступен через константу: Symbol.iterator

Давай сделаем это!

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

Примечание. Вы можете создать бесконечный цикл, если значение done итератора всегда ложно.

Код в v выше приведет к бесконечному циклу, если break statement не было добавлено, поскольку состояние итератора done всегда равно false. Это то, чего вам следует остерегаться!

Рассмотрение

Вы можете перебирать объекты с помощью синтаксиса for-of ES6 при условии, что они являются итеративными. for-of ищет встроенный или настраиваемый метод @@ iterator . Строки, Array, TypedArray, Maps и Set по умолчанию являются повторяемыми. По сути, все, что делает for-of, - это найти итератор и вызвать .next() на нем до done == true.

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

А сейчас до свидания! 👋