← Назад к вопросам

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

2.0 Middle🔥 111 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

for...in в массиве: ключи или значения?

Ответ: for...in возвращает ключи (индексы), не значения.

Это один из самых частых источников ошибок у JavaScript разработчиков.

Демонстрация

const fruits = ['apple', 'banana', 'cherry'];

// for...in - возвращает ИНДЕКСЫ (ключи)
for (const index in fruits) {
  console.log(index);    // '0', '1', '2' (строки!)
  console.log(fruits[index]); // 'apple', 'banana', 'cherry'
}

// Результат вывода:
// 0
// apple
// 1
// banana
// 2
// cherry

Почему индексы, а не значения?

for...in предназначена для итерации по объектам, а не массивам:

// Объект - for...in работает идеально
const user = {
  name: 'John',
  age: 30,
  email: 'john@example.com'
};

for (const key in user) {
  console.log(key);       // 'name', 'age', 'email'
  console.log(user[key]); // 'John', 30, 'john@example.com'
}

Массив - это тоже объект, с числовыми ключами:

const arr = ['a', 'b', 'c'];

// Внутренне это:
const arr = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};

// for...in итерирует по ключам, как и для объекта
for (const key in arr) {
  console.log(key); // '0', '1', '2'
}

Проблема: type вращается как строка

const numbers = [10, 20, 30];

for (const index in numbers) {
  console.log(typeof index);      // 'string'
  console.log(index);             // '0', '1', '2' (строки!)
  console.log(index + 1);         // '01', '11', '21' (конкатенация!)
}

// Результат:
// string
// 0
// 01      <- ОШИБКА! Ожидаем 1
// string
// 1
// 11      <- ОШИБКА! Ожидаем 2
// string
// 2
// 21      <- ОШИБКА! Ожидаем 3

Главная проблема: for...in итерирует по всем свойствам

const arr = ['a', 'b', 'c'];

// Добавляем свойство (не элемент массива)
arr.customProperty = 'hello';

for (const key in arr) {
  console.log(key);
}

// Результат:
// '0'
// '1'
// '2'
// 'customProperty'  <- ПРОБЛЕМА! Это не элемент массива

Правильные способы итерирации по массиву

1. for...of - для значений (рекомендуется)

const fruits = ['apple', 'banana', 'cherry'];

// for...of - возвращает ЗНАЧЕНИЯ
for (const fruit of fruits) {
  console.log(fruit); // 'apple', 'banana', 'cherry'
}

2. forEach - с индексом если нужен

const fruits = ['apple', 'banana', 'cherry'];

fruits.forEach((fruit, index) => {
  console.log(index, fruit);  // 0 'apple', 1 'banana', 2 'cherry'
});

3. for loop - классический способ

const fruits = ['apple', 'banana', 'cherry'];

for (let i = 0; i < fruits.length; i++) {
  console.log(i, fruits[i]);  // 0 'apple', 1 'banana', 2 'cherry'
}

4. map - для преобразования

const numbers = [1, 2, 3];

const doubled = numbers.map((num, index) => {
  console.log(index, num);  // 0 1, 1 2, 2 3
  return num * 2;
});

console.log(doubled); // [2, 4, 6]

Сравнение методов итерации

const arr = ['a', 'b', 'c'];

// 1. for...in - ключи объекта (НЕ для массивов!)
for (const key in arr) {
  console.log(key);        // '0', '1', '2'
  console.log(typeof key); // 'string'
}

// 2. for...of - значения (рекомендуется)
for (const value of arr) {
  console.log(value);      // 'a', 'b', 'c'
}

// 3. forEach - значение + индекс
arr.forEach((value, index) => {
  console.log(index, value); // 0 'a', 1 'b', 2 'c'
});

// 4. map - с преобразованием
const result = arr.map((value, index) => {
  return `${index}: ${value}`;
});
console.log(result); // ['0: a', '1: b', '2: c']

// 5. entries - ключ и значение одновременно
for (const [index, value] of arr.entries()) {
  console.log(index, value); // 0 'a', 1 'b', 2 'c'
}

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

Метод         | Возвращает      | Для чего               | Тип значения
──────────────┼─────────────────┼──────────────────────┼──────────────
for...in      | ключи           | объекты               | строка
for...of      | значения        | массивы, итерируемые  | любой
forEach       | значение+индекс | массивы               | любой
map           | новый массив    | преобразование        | любой
entries       | пара [индекс]   | массивы с индексами   | массив
while         | (ручное)        | любые                 | (ручное)
for (;;)      | (ручное)        | любые                 | (ручное)

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

Ошибка 1: for...in вместо for...of

// НЕПРАВИЛЬНО
const items = ['item1', 'item2', 'item3'];
for (const item in items) {
  console.log(item.toUpperCase()); // ERROR! item это '0', '1', '2' (строки)
}
// 0.toUpperCase() -> Error: 0 is not a function

// ПРАВИЛЬНО
for (const item of items) {
  console.log(item.toUpperCase()); // 'ITEM1', 'ITEM2', 'ITEM3'
}

Ошибка 2: Арифметика с индексом

const numbers = [10, 20, 30];

// НЕПРАВИЛЬНО
for (const i in numbers) {
  console.log(i + 5); // '05', '15', '25' (конкатенация!)
}

// ПРАВИЛЬНО
for (let i = 0; i < numbers.length; i++) {
  console.log(i + 5); // 5, 6, 7
}

Ошибка 3: Проверка свойств

const arr = [1, 2, 3];
arr.custom = 'value';

// НЕПРАВИЛЬНО - итерирует и custom
for (const key in arr) {
  console.log(arr[key]); // 1, 2, 3, 'value'
}

// ПРАВИЛЬНО
for (const value of arr) {
  console.log(value); // 1, 2, 3 (custom не включается)
}

Когда использовать for...in

// for...in ХОРОШ для объектов:
const config = {
  host: 'localhost',
  port: 3000,
  debug: true
};

for (const key in config) {
  console.log(`${key}: ${config[key]}`);
}
// host: localhost
// port: 3000
// debug: true

// for...in НЕ РЕКОМЕНДУЕТСЯ для массивов:
// Используй for...of вместо

Финальная рекомендация

// НИКОГДА не используй for...in для массивов:
const arr = [1, 2, 3];
for (const index in arr) {  // ❌ ПЛОХО
  // ...
}

// ВСЕГДА используй for...of:
for (const value of arr) {  // ✅ ХОРОШО
  // ...
}

// Или если нужен индекс:
arr.forEach((value, index) => {  // ✅ ХОРОШО
  // ...
});

// Или entries для пар:
for (const [index, value] of arr.entries()) {  // ✅ ХОРОШО
  // ...
}

Заключение

for...in в массиве возвращает индексы (ключи) как строки, а не значения. Это источник многих ошибок. Используй:

  • for...of для значений
  • forEach если нужен индекс
  • for...in только для объектов