Итерируемые объекты в JavaScript

Итерируемый объект - это значение, из которого JavaScript умеет получать элементы один за другим. Такие значения можно перебирать через for…of.

let numbers = [10, 20, 30];

for (let number of numbers) {
  console.log(number);
}

Результат:

10
20
30

Массив является итерируемым объектом, поэтому цикл for…of спокойно получает из него значения по порядку.

Что такое итерируемый объект

Если говорить простыми словами, итерируемый объект - это объект, который умеет отдавать свои элементы по одному.

JavaScript использует этот механизм в цикле for…of, операторе расширения , методе Array.from() и некоторых других местах.

Важно не путать: не любой объект в JavaScript является итерируемым. Массив - итерируемый. Строка - итерируемая. А обычный объект с фигурными скобками - нет.

Примеры итерируемых объектов

К итерируемым значениям относятся массивы.

let languages = ['HTML', 'CSS', 'JavaScript'];

for (let language of languages) {
  console.log(language);
}

Строки тоже можно перебирать.

let word = 'код';

for (let letter of word) {
  console.log(letter);
}

Результат:

к
о
д

Коллекции Set и Map также являются итерируемыми.

let skills = new Set(['HTML', 'CSS', 'JavaScript']);

for (let skill of skills) {
  console.log(skill);
}

Map при переборе возвращает пары: ключ и значение.

let prices = new Map([
  ['book', 500],
  ['course', 1500]
]);

for (let [name, price] of prices) {
  console.log(name + ': ' + price);
}

for…of и итерируемые объекты

Цикл for…of работает именно с итерируемыми объектами.

for (let value of iterable) {
  // действие с value
}

iterable - итерируемый объект.

value - очередное значение, которое цикл получил на текущей итерации.

let numbers = [1, 2, 3];

for (let number of numbers) {
  console.log(number * 2);
}

Результат:

2
4
6

На каждой итерации цикл получает очередное число из массива и записывает его в переменную number.

Где еще используются итерируемые объекты

Итерируемые объекты можно разворачивать через оператор .

let numbers = [1, 2, 3];
let copy = [...numbers];

console.log(copy);

Результат:

[1, 2, 3]

Строку можно превратить в массив символов через Array.from().

let letters = Array.from('код');

console.log(letters);

Результат:

['к', 'о', 'д']

Оба примера работают потому, что массив и строка являются итерируемыми.

Обычный объект не итерируемый

Обычный объект нельзя напрямую перебрать через for…of.

let user = {
  name: 'Анна',
  age: 25
};

for (let value of user) {
  console.log(value);
}

Такой код приведет к ошибке, потому что объект user не является итерируемым.

Если нужно перебрать обычный объект, сначала можно получить массив ключей, значений или пар.

let user = {
  name: 'Анна',
  age: 25
};

for (let value of Object.values(user)) {
  console.log(value);
}

Результат:

Анна
25

Object.values(user) возвращает массив, а массив уже можно перебрать через for…of.

Связь с Symbol.iterator

Технически итерируемым считается объект, у которого есть специальный метод Symbol.iterator.

let numbers = [1, 2, 3];

console.log(typeof numbers[Symbol.iterator]);

Результат:

function

Это значит, что массив умеет отдавать значения по одному.

Подробно Symbol.iterator и метод next() лучше разбирать отдельно. Сейчас достаточно запомнить связь: если значение итерируемое, его можно использовать в for…of.

Итого

1. Итерируемый объект - это значение, из которого JavaScript умеет получать элементы один за другим.

2. Массивы, строки, Set и Map являются итерируемыми.

3. Цикл for…of работает с итерируемыми объектами.

4. Обычный объект не является итерируемым, но его можно перебрать через Object.keys(), Object.values() или Object.entries().

5. За возможность перебора отвечает специальный метод Symbol.iterator.