The delete operator on an array
delete arr[0] removes the value at index 0, but it does not shift the remaining elements and does not change length: an empty item (a hole) is left in place of the deleted element. Formally the array does not delete an element, it deletes the property with the key 0, which makes the array structure ragged.
Theory
TL;DR
- The element at index
0disappears, but its slot stays empty. lengthdoes not change: it was3, it stays3.- The remaining elements are not shifted to the left.
- A hole appears in the array, a so called empty slot:
0 in arrreturnsfalse. - Iteration methods (
forEach,map,filter) skip empty slots, while a direct read ofarr[0]givesundefined. - To really remove an element, with a shift, use
splice().
Quick example
const arr = [10, 20, 30];
delete arr[0];
console.log(arr); // [ <1 empty item>, 20, 30 ]
console.log(arr.length); // 3The value 10 is gone, yet the array still has a length of 3.
What happens under the hood
deleteis an operator for objects: it removes a property. An array in JavaScript is also an object, just one with numeric keys0,1,2and a speciallengthproperty.- So
delete arr[0]literally means "delete the property named0". - The operator does not shift the other elements: the keys
1and2stay where they are. - The operator does not touch
length: the length is a separate property and is not recalculated automatically.
The result is a hole in the array, a so called empty slot (a sparse array).
Demonstrating the hole
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, the element really is not thereNote the difference between an empty slot and the value undefined:
const holes = [1, , 3]; // an empty slot
const undef = [1, undefined, 3]; // a real undefined value
console.log(1 in holes); // false
console.log(1 in undef); // trueBoth arrays return undefined at index 1, but only in the second case does the property actually exist.
Why this is not recommended
Empty cells behave oddly and easily break the logic of your code.
-
forEach,map,filter,reduce,some,everyandObject.keysskip such positions:javascriptconst arr = [1, 2, 3]; delete arr[1]; arr.forEach(el => console.log(el)); // logs only 1 and 3 -
But a direct read (
arr[1]) gives youundefined, so a check againstundefinedcannot tell a hole from a real value. -
Some of the newer methods do the opposite and treat a slot as
undefined:Array.from(arr), the spread[...arr],for...of,join(),includes(). Because of that the same array behaves differently in different parts of the code. -
JavaScript engines optimise dense arrays; a sparse array can push the internal representation into a slower mode.
The correct way to remove an element
Use splice() when you need to remove an element and shift the rest:
const arr = [10, 20, 30];
arr.splice(0, 1);
console.log(arr); // [20, 30]
console.log(arr.length); // 2If mutating the array is not allowed, build a new copy without the unwanted element:
const arr = [10, 20, 30];
const withoutFirst = arr.slice(1); // [20, 30]
const withoutIndex = arr.filter((_, i) => i !== 0); // [20, 30]For the first and last element there are shorter options: shift() and pop(), and both update length correctly.
A short comparison
| Method | What it does | Changes length | Creates a hole? |
|---|---|---|---|
delete arr[i] | removes a property | No | Yes |
arr.splice(i, 1) | removes an element and shifts the rest | Yes | No |
arr.filter(...) | returns a new array without the element | The new array is shorter | No |
Conclusion: avoid
delete arr[index]for arrays, because it leaves empty slots and makes the structure ragged. For a safe removal usesplice().
Common mistakes
- Expecting
lengthto shrink. It never does:deleteknows nothing about array semantics. - Assuming the elements will shift. The indexes of the remaining elements stay the same, so after
delete arr[0]the expressionarr[1]is still the second element. - Confusing an empty slot with
undefined. Check for presence withi in arrorObject.hasOwn(arr, i), not witharr[i] === undefined. - Expecting every method to behave the same. The older iteration methods skip holes, while spread,
for...ofandArray.fromturn them intoundefined. - Using
deleteto clear an array. To empty an array usearr.length = 0orarr.splice(0). - Forgetting that
deletereturnstruealmost always. A successful return does not mean the array got shorter.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.