Skip to main content

Звертання до неіснуючого індексу

Якщо звернутися до неіснуючого індексу масиву, JavaScript поверне undefined, і помилки при цьому не буде. Це не баг, а наслідок того, що масив, це об'єкт, а читання відсутньої властивості об'єкта в JavaScript завжди безпечне.

Теорія

TL;DR

  • Читання неіснуючого індексу дає undefined, виняток не кидається.
  • Причина: масив, це об'єкт, індекси, це рядкові ключі, а відсутня властивість повертає undefined.
  • undefined тут означає «значення відсутнє», а не «сталася помилка».
  • TypeError буде тільки тоді, коли не існує сам масив: null або undefined.
  • Перевірити наявність елемента можна через index in arr або Object.hasOwn(arr, index).
  • Порожній слот («дірка») теж дає undefined, але in для нього поверне false.

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

javascript
const arr = ['apple', 'banana', 'cherry']; console.log(arr[0]); // 'apple' console.log(arr[3]); // undefined, елемента немає console.log(arr[10]); // undefined, і теж без помилки

Жодне з цих звертань не зупиняє виконання коду.

Чому так відбувається

У JavaScript масив, це об'єкт, у якому індекси, це рядкові ключі:

javascript
// приблизно еквівалентно const arr = { '0': 'apple', '1': 'banana', '2': 'cherry', length: 3 };

Якщо звернутися до неіснуючої властивості, JavaScript поверне undefined, а не кине виняток, як це робить, наприклад, Python зі своїм IndexError або Java з ArrayIndexOutOfBoundsException.

Те саме працює і для від'ємних чи дробових індексів: вони просто стають звичайними рядковими ключами, яких в об'єкті немає.

javascript
const arr = [1, 2, 3]; console.log(arr[-1]); // undefined, це ключ '-1', а не «останній елемент» console.log(arr[1.5]); // undefined console.log(arr.at(-1)); // 3, ось так беруть останній елемент

Коли помилка все ж буде

undefined означає «значення відсутнє», а не «помилка». Але якщо ви намагаєтеся звернутися до індексу масиву, якого не існує взагалі, тобто сам масив дорівнює undefined чи null, тоді буде виняток:

javascript
const arr = undefined; console.log(arr[0]); // TypeError: Cannot read properties of undefined

Убезпечитися допомагає опціональне звертання:

javascript
const arr = undefined; console.log(arr?.[0]); // undefined, без помилки console.log(arr?.[0] ?? 0); // 0, значення за замовчуванням

Як перевірити наявність елемента

javascript
const arr = [1, 2, 3]; console.log(2 in arr); // true, елемент з індексом 2 є console.log(5 in arr); // false, елемента немає

Сучасніша й безпечніша альтернатива, це Object.hasOwn():

javascript
console.log(Object.hasOwn(arr, 2)); // true console.log(Object.hasOwn(arr, 5)); // false

Перевірка arr[i] !== undefined для цього не годиться: вона не відрізнить відсутній елемент від збереженого значення undefined.

javascript
const values = [1, undefined, 3]; console.log(values[1] !== undefined); // false, хоча елемент існує console.log(1 in values); // true

Приклад з «дірками» (порожніми слотами)

javascript
const arr = [1, , 3]; // пропущений елемент console.log(arr[1]); // undefined console.log(1 in arr); // false, комірки справді немає

Тобто arr[1] дасть undefined, але слот при цьому не існує: це порожня комірка, а не збережене значення undefined.

Коротка таблиця

СитуаціяРезультатПомилка?
Індекс існуєповертає значенняНі
Індексу немаєundefinedНі
Масив не існує (null або undefined)TypeErrorТак
Порожній слот (дірка)undefined, але index in arr дає falseНі

Підсумок: звертання до неіснуючого індексу масиву повертає undefined, але не викликає помилку. Така поведінка, це частина гнучкості JavaScript.

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

  • Очікувати виняток, як в інших мовах. Вихід за межі масиву в JavaScript мовчазний, тому помилку ви побачите значно пізніше, уже на undefined.
  • Плутати «немає елемента» і «значення undefined». Порівняння з undefined не дає відповіді, беріть in або Object.hasOwn().
  • Використовувати arr[-1] як останній елемент. Це просто ключ '-1'; для останнього елемента є arr.at(-1) або arr[arr.length - 1].
  • Забувати перевірити сам масив. Якщо дані прийшли з мережі, змінна може бути undefined, і тоді звертання кине TypeError; захистіться через arr?.[i].
  • Ланцюжок звертань без перевірки. arr[10].name кине TypeError, бо undefined не має властивостей; пишіть arr[10]?.name.
  • Запис у великий індекс. arr[100] = 1 не кине помилку, а розтягне length до 101 і створить дірки.

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

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

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