Skip to main content

Різні типи даних в одному масиві

Так, у JavaScript в одному масиві можна зберігати дані різних типів. Це одна з ключових особливостей мови: масив не типізований, тому його елементами можуть бути числа, рядки, об'єкти, функції і навіть інші масиви.

Теорія

TL;DR

  • Масив у JavaScript не типізований: обмежень на типи елементів немає.
  • Причина в тому, що масив, це об'єкт, де індекси, це ключі ("0", "1", "2"), а значення можуть бути будь-якими.
  • JavaScript динамічно типізований, тому тип елемента не фіксується при створенні масиву.
  • Технічна можливість не означає, що так варто робити: зазвичай краще зберігати однорідні дані.
  • Для різнорідних даних природнішою структурою є об'єкт з іменованими полями.
  • Якщо змішаний масив таки потрібен, перед обробкою перевіряйте тип кожного елемента.

Швидкий приклад

javascript
const mixed = [ 42, // число 'hello', // рядок true, // булеве значення { name: 'Tim' }, // об'єкт [1, 2, 3], // вкладений масив function () { return 'JS'; } // функція ]; console.log(mixed[0]); // 42 console.log(mixed[1]); // "hello" console.log(mixed[3].name); // "Tim" console.log(mixed[4][1]); // 2 console.log(mixed[5]()); // "JS"

Кожен елемент живе за своїм індексом і поводиться відповідно до власного типу: до об'єкта звертаємось через крапку, до вкладеного масиву через другий індекс, функцію викликаємо дужками.

Чому це можливо

  • У JavaScript масив, це об'єкт, у якого індекси, це ключі ("0", "1", "2", ...), а значення можуть бути будь-якого типу.
  • JavaScript, це динамічно типізована мова, тому тип елемента не фіксується в момент створення масиву.

Це легко перевірити: типи можна змінювати вже після створення, і масив не заперечуватиме.

javascript
const items = [1, 2, 3]; items[0] = 'now a string'; items.push(null, undefined, Symbol('id')); console.log(items.length); // 6

Але варто пам'ятати

  • Хоча так робити можна, для зручності та читабельності коду зазвичай намагаються зберігати однорідні дані, наприклад список чисел або список об'єктів.
  • Якщо в масиві багато різних типів, працювати з ним стає складніше: методи map, filter, sort і reduce доводиться обвішувати перевірками типу.
  • Однорідний масив ще й швидший: рушії оптимізують масиви, у яких усі елементи одного виду, а змішування типів переводить масив у повільніше внутрішнє представлення.
  • Коли елементи мають різний зміст, а не різний тип, замість масиву краще взяти об'єкт з іменованими полями: { id: 1, title: 'text', active: true }.

Як безпечно обробляти змішаний масив

Якщо змішаний масив таки потрібен, наприклад це розібрані дані з форми або зовнішньої відповіді, перевіряйте тип перед обробкою.

javascript
const mixed = [42, 'hello', true, { name: 'Tim' }, [1, 2, 3]]; const numbers = mixed.filter((item) => typeof item === 'number'); const arrays = mixed.filter((item) => Array.isArray(item)); console.log(numbers); // [42] console.log(arrays); // [[1, 2, 3]]

Пам'ятайте, що typeof не розрізняє масив і об'єкт (обидва дають "object"), тому для масиву потрібен Array.isArray().

Коротко

ПитанняВідповідь
Чи можна зберігати різні типи?Так
Чому?Масив, це об'єкт, а JavaScript динамічно типізований
Чи рекомендується?Тільки якщо це справді потрібно
Приклад[1, 'text', true, { id: 1 }, [5, 6], () => {}]

Типові помилки

  • Викликати методи, не перевіривши тип. mixed.map((x) => x.toUpperCase()) впаде на першому ж числі або на null.
  • Сортувати змішаний масив. sort() без компаратора порівнює рядкові представлення, тож [10, 'a', true].sort() дасть несподіваний порядок.
  • Плутати масив і об'єкт усередині масиву. Для елемента-масиву typeof поверне "object", тому потрібен Array.isArray(item).
  • Зберігати різнорідні поля одного запису як масив. ['Tim', 25, true] читається гірше, ніж { name: 'Tim', age: 25, active: true }, і ламається при зміні порядку.
  • Розраховувати на однакову поведінку в TypeScript. Там масив типізований, і для змішаних значень доведеться описувати union або кортеж: (number | string)[] чи [string, number].

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.