Цикл for...in

Цикл for...in

Технический фундамент for...in

for...in - это цикл по перечислимым именам свойств объекта. Он возвращает ключи (включая потенциально унаследованные), а доступ к значениям выполняется отдельно через индексную нотацию.

Ключевой момент: for...in проходит по именам свойств, а не по значениям и не по итератору.

Проверь себя: почему for...in и for...of нельзя считать взаимозаменяемыми?

Базовый синтаксис

const user = {
  name: 'Anna',
  role: 'student',
  isActive: true,
};

for (const key in user) {
  console.log(key, user[key]);
}

Смотри, что важно: значение берется через user[key], потому что key - динамическая строка.

for...in и объекты

Это основной сценарий for...in.

const settings = { theme: 'dark', lang: 'ru' };

for (const key in settings) {
  console.log(`${key}: ${settings[key]}`);
}

Цикл полезен, когда заранее неизвестно, какие именно поля пришли.

Почему не стоит использовать for...in для массива

for...in по массиву вернет индексы как строки, и поведение может быть неочевидным.

const arr = [10, 20, 30];
for (const key in arr) {
  console.log(key); // '0', '1', '2'
}

Для массивов обычно лучше for...of или классический for.

Здесь часто путаются: for...in технически "работает" для массива, но не лучший выбор по смыслу.

Проверь себя: какой цикл ты выберешь, если нужен именно элемент массива, а не его индекс?

Защита от унаследованных свойств

for...in может пройти по унаследованным перечислимым свойствам. В прикладном коде чаще фильтруют только собственные.

const base = { inherited: 1 };
const obj = Object.create(base);
obj.own = 2;

for (const key in obj) {
  console.log(key); // 'own', 'inherited'
}
for (const key in obj) {
  if (Object.hasOwn(obj, key)) {
    console.log(key, obj[key]);
  }
}

Смотри, что важно: это особенно актуально в универсальных утилитах, где объект приходит извне.

Мини-сценарий: валидация полей формы

const form = { email: 'a@mail.com', age: 20, agreed: true };

for (const key in form) {
  if (form[key] === null || form[key] === undefined) {
    console.log('missing:', key);
  }
}

for...in здесь удобен, потому что проверка одинаковая для всех ключей объекта.

Дополнительный пример для новичка: собрать только заполненные поля

const profile = { name: 'Ann', city: '', age: 20 };
const filled = {};

for (const key in profile) {
  if (!Object.hasOwn(profile, key)) continue;
  if (profile[key] === '') continue;
  filled[key] = profile[key];
}

console.log(filled); // { name: 'Ann', age: 20 }

Здесь видно сразу две базовые техники: фильтрация собственных свойств и работа с динамическим ключом через obj[key].

Частые ошибки новичков

  • Применять for...in к массивам без причины.
  • Путать ключ и значение в теле цикла.
  • Забывать про фильтр собственных свойств.
  • Использовать точечную нотацию obj.key вместо obj[key] внутри цикла.

Анти-провал: если цель - значения массива, бери for...of; если цель - ключи объекта, бери for...in.

Что будет, если изменить входные данные

Если в объекте появятся новые поля, for...in автоматически начнет их обрабатывать - это плюс для универсальных проверок. Но если объект содержит неожиданные унаследованные свойства, без hasOwn ты можешь обработать лишнее.

Проверь себя: в каких сценариях фильтр Object.hasOwn обязателен?

Краткий итог

  • for...in предназначен для перебора ключей объекта.
  • Внутри цикла значение берут через obj[key].
  • Для массивов этот цикл обычно не лучший выбор.
  • В надежном коде полезно фильтровать только собственные свойства.
  • Правильный выбор цикла по типу данных делает логику чище и безопаснее.