Итерируемым (перечисляемым) считается любой объект, который реализует символьное свойство Symbol.iterator
. Ряд встроенных в JavaScript типов, таких как Array
, String
, Map
, Set
, уже имеют свойство Symbol.iterator
и реализуют его, таким образом являясь итерируемыми.
Если у объектов такого типа вызвать функцию Symbol.iterator
, то вернется функционал (функция next()
), позволяющий перебирать данный объект в цикле. В ответе же на вызов функции next()
должен возвращаться объект с двумя свойствами:
done
- булево значение, показывающее, закончен ли перебор;value
- значение следующего итерируемого элемента.
Пример:
let list = [1, 2, 3];
let listIterator = list[Symbol.iterator]();
console.log(listIterator.next().value); // 1
console.log(listIterator.next().done); // false
console.log(listIterator.next().value); // 3
console.log(listIterator.next().done); // true
Таким образом, можно создавать свои итерируемые объекты и самим реализовывать какой-то свой кастомный перебор таких объектов.
Цикл for..of
Производит перебор элементов итерируемого объекта с использованием функции Symbol.iterator
:
let list = [3, 4, 5];
for (let val of list) {
console.log(val); // 3, 4, 5
}
Отличие for..of
от for..in
for..in
возвращает список ключей итерируемого объекта, тогда как for..of
возвращает список значений его свойств:
let list = [3, 4, 5];
for (let i in list) {
console.log(i); // 0, 1, 2
}
for (let i of list) {
console.log(i); // 3, 4, 5
}
Транспилированный код
Если компилятор TypeScript настроен на соответствие требованиям ES3 или ES5, то цикл for..of
будет преобразован в следующий код:
for (var _i = 0, list_1 = list; _i < list_1.length; _i++) {
var i = list_1[_i];
console.log(i); // 3, 4, 5
}
При этом, если попытаться использовать цикл for..of
на объектах, тип которых отличен от Array
, даже если эти объекты реализуют Symbol.iterator
, TypeScript сообщит об ошибке.