Оператор delete на масиві
delete arr[0] прибирає значення з нульової позиції, але не зсуває решту елементів і не змінює length: на місці видаленого елемента лишається порожній слот (empty item). Формально масив видаляє не елемент, а властивість з ключем 0, тому структура масиву стає «рваною».
Теорія
TL;DR
- Елемент з індексом
0зникає, але його місце залишається порожнім (empty). lengthне змінюється: був3, залишиться3.- Решта елементів не зсувається вліво.
- У масиві з'являється «дірка», тобто порожній слот:
0 in arrповернеfalse. - Методи перебору (
forEach,map,filter) порожні слоти пропускають, а пряме звертанняarr[0]даєundefined. - Щоб видалити елемент по-справжньому, зі зсувом, потрібен
splice().
Швидкий приклад
const arr = [10, 20, 30];
delete arr[0];
console.log(arr); // [ <1 empty item>, 20, 30 ]
console.log(arr.length); // 3Значення 10 зникло, але масив і далі має довжину 3.
Що відбувається «під капотом»
delete, це оператор для об'єктів: він видаляє властивість. Масив у JavaScript, це теж об'єкт, просто з числовими ключами0,1,2і спеціальною властивістюlength.- Тому
delete arr[0]означає буквально «видали властивість з ім'ям0». - Оператор не зсуває інші елементи: ключі
1і2залишаються на своїх місцях. - Оператор не чіпає
length: довжина масиву задається окремою властивістю і автоматично не перераховується.
У підсумку в масиві утворюється «дірка», так званий порожній слот (sparse array).
Демонстрація «дірки»
const arr = [1, 2, 3];
delete arr[1];
console.log(arr); // [1, <1 empty item>, 3]
console.log(arr.length); // 3
console.log(1 in arr); // false, елемента справді немаєЗверніть увагу на різницю між порожнім слотом і значенням undefined:
const holes = [1, , 3]; // порожній слот
const undef = [1, undefined, 3]; // справжнє значення undefined
console.log(1 in holes); // false
console.log(1 in undef); // trueОбидва масиви на позиції 1 повертають undefined, але лише в другому випадку властивість реально існує.
Чому так робити не варто
Порожні комірки поводяться незвично і легко ламають логіку коду.
-
forEach,map,filter,reduce,some,everyтаObject.keysтакі позиції пропускають:javascriptconst arr = [1, 2, 3]; delete arr[1]; arr.forEach(el => console.log(el)); // виведе тільки 1 і 3 -
Але при прямому звертанні (
arr[1]) ви отримаєтеundefined, тому перевірка наundefinedне відрізнить порожній слот від реального значення. -
Частина сучасніших методів, навпаки, трактує слот як
undefined:Array.from(arr), spread[...arr],for...of,join(),includes(). Через це той самий масив у різних місцях коду поводиться по-різному. -
Двигуни JavaScript оптимізують щільні масиви; розріджений масив може перевести внутрішнє представлення у повільніший режим.
Правильний спосіб видалити елемент
Використовуйте splice(), якщо потрібно видалити елемент і зсунути решту:
const arr = [10, 20, 30];
arr.splice(0, 1);
console.log(arr); // [20, 30]
console.log(arr.length); // 2Якщо масив мутувати не можна, зробіть нову копію без зайвого елемента:
const arr = [10, 20, 30];
const withoutFirst = arr.slice(1); // [20, 30]
const withoutIndex = arr.filter((_, i) => i !== 0); // [20, 30]Для першого й останнього елемента є коротші варіанти: shift() і pop(), і обидва коректно оновлюють length.
Коротке порівняння
| Метод | Що робить | Змінює length | Створює «дірку»? |
|---|---|---|---|
delete arr[i] | видаляє властивість | Ні | Так |
arr.splice(i, 1) | видаляє елемент і зсуває решту | Так | Ні |
arr.filter(...) | повертає новий масив без елемента | Новий масив коротший | Ні |
Висновок:
delete arr[index]для масивів краще не використовувати, бо він залишає порожні слоти і робить структуру «рваною». Для безпечного видалення берітьsplice().
Типові помилки
- Очікувати, що
lengthзменшиться. Він не зменшується ніколи:deleteне знає про семантику масиву. - Думати, що елементи зсунуться. Індекси решти елементів залишаються тими самими, тому
arr[1]післяdelete arr[0]і далі дорівнює другому елементу. - Плутати порожній слот з
undefined. Перевіряйте наявність черезi in arrабоObject.hasOwn(arr, i), а не черезarr[i] === undefined. - Розраховувати на однакову поведінку всіх методів. Старі методи перебору дірки пропускають, а spread,
for...ofіArray.fromперетворюють їх наundefined. - Використовувати
deleteдля очищення масиву. Щоб спорожнити масив, єarr.length = 0абоarr.splice(0). - Забувати, що
deleteповертаєtrueмайже завжди. Успішне повернення не означає, що масив став коротшим.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.