Звертання до неіснуючого індексу
Якщо звернутися до неіснуючого індексу масиву, JavaScript поверне undefined, і помилки при цьому не буде. Це не баг, а наслідок того, що масив, це об'єкт, а читання відсутньої властивості об'єкта в JavaScript завжди безпечне.
Теорія
TL;DR
- Читання неіснуючого індексу дає
undefined, виняток не кидається. - Причина: масив, це об'єкт, індекси, це рядкові ключі, а відсутня властивість повертає
undefined. undefinedтут означає «значення відсутнє», а не «сталася помилка».TypeErrorбуде тільки тоді, коли не існує сам масив:nullабоundefined.- Перевірити наявність елемента можна через
index in arrабоObject.hasOwn(arr, index). - Порожній слот («дірка») теж дає
undefined, алеinдля нього повернеfalse.
Швидкий приклад
const arr = ['apple', 'banana', 'cherry'];
console.log(arr[0]); // 'apple'
console.log(arr[3]); // undefined, елемента немає
console.log(arr[10]); // undefined, і теж без помилкиЖодне з цих звертань не зупиняє виконання коду.
Чому так відбувається
У JavaScript масив, це об'єкт, у якому індекси, це рядкові ключі:
// приблизно еквівалентно
const arr = { '0': 'apple', '1': 'banana', '2': 'cherry', length: 3 };Якщо звернутися до неіснуючої властивості, JavaScript поверне undefined, а не кине виняток, як це робить, наприклад, Python зі своїм IndexError або Java з ArrayIndexOutOfBoundsException.
Те саме працює і для від'ємних чи дробових індексів: вони просто стають звичайними рядковими ключами, яких в об'єкті немає.
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, тоді буде виняток:
const arr = undefined;
console.log(arr[0]); // TypeError: Cannot read properties of undefinedУбезпечитися допомагає опціональне звертання:
const arr = undefined;
console.log(arr?.[0]); // undefined, без помилки
console.log(arr?.[0] ?? 0); // 0, значення за замовчуваннямЯк перевірити наявність елемента
const arr = [1, 2, 3];
console.log(2 in arr); // true, елемент з індексом 2 є
console.log(5 in arr); // false, елемента немаєСучасніша й безпечніша альтернатива, це Object.hasOwn():
console.log(Object.hasOwn(arr, 2)); // true
console.log(Object.hasOwn(arr, 5)); // falseПеревірка arr[i] !== undefined для цього не годиться: вона не відрізнить відсутній елемент від збереженого значення undefined.
const values = [1, undefined, 3];
console.log(values[1] !== undefined); // false, хоча елемент існує
console.log(1 in values); // trueПриклад з «дірками» (порожніми слотами)
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і створить дірки.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.