React Front-end Инженер

React Front-end Инженер

Роадмап навыков для прокачки

Цикл for...of

JavaScript (ES6 и новее)Общие возможности ES6По умолчанию

Основная идея

Цикл for...of — это современный синтаксис ES6 для перебора итерируемых объектов (массивов, строк, Map, Set и др.). В отличие от for...in, который перебирает ключи, for...of перебирает значения элементов.

Ключевые аспекты

  • Работает с итерируемыми объектами — массивы, строки, Map, Set, NodeList, arguments
  • Перебирает значения, а не индексы или ключи
  • Не работает с обычными объектами — для объектов используйте for...in или Object.entries()
  • Поддерживает break и continue — в отличие от forEach()
  • Чистый синтаксис — не требует работы с индексами

Плюсы

  • Простой и читаемый синтаксис
  • Автоматическое получение значений без индексации
  • Работает с любыми итерируемыми объектами
  • Можно прервать цикл через break

Минусы

  • Нет доступа к индексу элемента напрямую (используйте entries())
  • Не работает с обычными объектами {}
  • Медленнее классического for на больших массивах

Частые ошибки на собеседованиях

  • Путают for...of и for...in — первый для значений, второй для ключей
  • Пытаются использовать for...of с обычными объектами — получают TypeError
  • Забывают, что строки тоже итерируемые — for...of перебирает символы

Введение и проблематика

До ES6 для перебора массивов использовался классический цикл for с индексами или метод forEach(). Оба подхода имели недостатки: громоздкий синтаксис с индексами или невозможность прервать цикл.

Цикл for...of появился в ES6 (2015) как элегантное решение для перебора итерируемых коллекций.

Какую проблему решает?

Code Example 1: В чём разница между этими двумя способами перебора массива? Какой из них удобнее и почему?

js
// ❌ Классический for — много лишнего кода
const fruits = ['яблоко', 'банан', 'апельсин'];
for (let i = 0; i < fruits.length; i++) {
  console.log(fruits[i]);
}
 
// ✅ for...of — чистый и понятный
for (const fruit of fruits) {
  console.log(fruit);
}

Базовая теория

Синтаксис

js
for (const element of iterable) {
  // работа с element
}
  • element — текущее значение на каждой итерации
  • iterable — любой итерируемый объект

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

for...of работает с объектами, которые реализуют протокол итератора:

ТипПримерЧто перебирается
Array[1, 2, 3]Элементы массива
String'hello'Символы строки
Mapnew Map()Пары [key, value]
Setnew Set()Уникальные значения
NodeListdocument.querySelectorAll()DOM-элементы
argumentsargumentsАргументы функции
⚠️

Обычные объекты {} не итерируемые! Для них for...of выбросит TypeError.


Практические примеры

Перебор массива

js
const numbers = [10, 20, 30];
 
for (const num of numbers) {
  console.log(num); // 10, 20, 30
}

Перебор строки

Code Example 2: Что выведет этот цикл? Можно ли использовать for...of для строк?

js
const word = 'Привет';
 
for (const char of word) {
  console.log(char); // П, р, и, в, е, т
}

Использование с деструктуризацией

Code Example 3: Как работает деструктуризация внутри for...of? Что выведет этот код?

js
const users = [
  { name: 'Анна', age: 25 },
  { name: 'Борис', age: 30 }
];
 
for (const { name, age } of users) {
  console.log(`${name}: ${age} лет`);
}
// Анна: 25 лет
// Борис: 30 лет

Получение индекса через entries()

Code Example 4: Как получить индекс элемента в for...of? Что выведет этот цикл?

js
const colors = ['красный', 'зелёный', 'синий'];
 
for (const [index, color] of colors.entries()) {
  console.log(`${index}: ${color}`);
}
// 0: красный
// 1: зелёный
// 2: синий

Сравнение for...of и for...in

Code Example 5: Что выведет каждый цикл? В чём принципиальная разница между for...of и for...in?

js
const arr = ['a', 'b', 'c'];
 
// Перебирает ЗНАЧЕНИЯ
for (const value of arr) {
  console.log(value); // 'a', 'b', 'c'
}

Таблица сравнения

Аспектfor...offor...in
ПеребираетЗначенияКлючи (свойства)
Массивы✅ Элементы⚠️ Индексы как строки
Объекты❌ TypeError✅ Ключи объекта
ПрототипИгнорируетВключает
ИспользованиеМассивы, коллекцииОбъекты
🚫

Антипаттерн: Использование for...in для массивов — перебирает индексы как строки и может захватить свойства из прототипа.


Пограничные кейсы

Прерывание цикла

Code Example 6: Что выведут эти циклы? Можно ли использовать break и continue в for...of?

js
const numbers = [1, 2, 3, 4, 5];
 
for (const num of numbers) {
  if (num === 3) break; // ✅ Работает!
  console.log(num); // 1, 2
}

Пропуск итерации

js
const numbers = [1, 2, 3, 4, 5];
 
for (const num of numbers) {
  if (num % 2 === 0) continue; // пропускаем чётные
  console.log(num); // 1, 3, 5
}

Работа с Map

Code Example 7: Как for...of работает с Map и Set? Что выведет каждый цикл?

js
const userRoles = new Map([
  ['admin', 'Администратор'],
  ['user', 'Пользователь']
]);
 
for (const [key, value] of userRoles) {
  console.log(`${key}: ${value}`);
}

Работа с Set

js
const uniqueNumbers = new Set([1, 2, 2, 3, 3, 3]);
 
for (const num of uniqueNumbers) {
  console.log(num); // 1, 2, 3
}

Работа с объектами

⚠️

Обычные объекты не поддерживают for...of. Используйте Object.keys(), Object.values() или Object.entries().

Code Example 8: Почему for...of не работает с обычными объектами? Как обойти это ограничение?

js
const user = { name: 'Иван', age: 30, city: 'Москва' };
 
// ❌ Ошибка: user is not iterable
// for (const value of user) {}
 
// ✅ Правильно: через Object.entries()
for (const [key, value] of Object.entries(user)) {
  console.log(`${key}: ${value}`);
}
// name: Иван
// age: 30
// city: Москва

Плюсы и минусы

ПлюсыМинусы
Чистый, читаемый синтаксисНет прямого доступа к индексу
Работает с break/continueНе работает с обычными объектами
Поддерживает все итерируемые типыЧуть медленнее классического for
Безопасен от ошибок с индексамиТребует ES6+

Вопросы интервьюера

Q: В чём разница между for...of и for...in?

for...of перебирает значения итерируемых объектов (массивы, строки, Map, Set). for...in перебирает ключи/свойства объектов, включая унаследованные.

Q: Как получить индекс элемента в for...of?

Используйте метод entries(): for (const [index, value] of array.entries()).

Q: Почему for...of не работает с объектами?

Обычные объекты не реализуют протокол итератора. Используйте Object.entries(), Object.keys() или Object.values().

Q: Когда лучше использовать forEach(), а когда for...of?

for...of позволяет использовать break и continue, работает с async/await. forEach() более функциональный, но не поддерживает прерывание.


Источники

Code Example 1: Классический for vs for...of

❓ В чём разница между этими двумя способами перебора массива? Какой из них удобнее и почему?

js
const fruits = ['яблоко', 'банан', 'апельсин'];
for (let i = 0; i < fruits.length; i++) {
  console.log(fruits[i]);
}
 
for (const fruit of fruits) {
  console.log(fruit);
}

Code Example 2: Перебор строки

❓ Что выведет этот цикл? Можно ли использовать for...of для строк?

js
const word = 'Привет';
 
for (const char of word) {
  console.log(char);
}

Code Example 3: Деструктуризация в for...of

❓ Как работает деструктуризация внутри for...of? Что выведет этот код?

js
const users = [
  { name: 'Анна', age: 25 },
  { name: 'Борис', age: 30 }
];
 
for (const { name, age } of users) {
  console.log(`${name}: ${age} лет`);
}

Code Example 4: Получение индекса через entries()

❓ Как получить индекс элемента в for...of? Что выведет этот цикл?

js
const colors = ['красный', 'зелёный', 'синий'];
 
for (const [index, color] of colors.entries()) {
  console.log(`${index}: ${color}`);
}

Code Example 5: for...of vs for...in

❓ Что выведет каждый цикл? В чём принципиальная разница между for...of и for...in?

for...of:

js
const arr = ['a', 'b', 'c'];
 
for (const value of arr) {
  console.log(value);
}

for...in:

js
const arr = ['a', 'b', 'c'];
 
for (const key in arr) {
  console.log(key);
}

Code Example 6: break и continue

❓ Что выведут эти циклы? Можно ли использовать break и continue в for...of?

js
const numbers = [1, 2, 3, 4, 5];
 
for (const num of numbers) {
  if (num === 3) break;
  console.log(num);
}
 
for (const num of numbers) {
  if (num % 2 === 0) continue;
  console.log(num);
}

Code Example 7: Работа с Map и Set

❓ Как for...of работает с Map и Set? Что выведет каждый цикл?

js
const userRoles = new Map([
  ['admin', 'Администратор'],
  ['user', 'Пользователь']
]);
 
for (const [key, value] of userRoles) {
  console.log(`${key}: ${value}`);
}
 
const uniqueNumbers = new Set([1, 2, 2, 3, 3, 3]);
 
for (const num of uniqueNumbers) {
  console.log(num);
}

Code Example 8: for...of с объектами

❓ Почему for...of не работает с обычными объектами? Как обойти это ограничение?

js
const user = { name: 'Иван', age: 30, city: 'Москва' };
 
for (const [key, value] of Object.entries(user)) {
  console.log(`${key}: ${value}`);
}