Skip to content Skip to sidebar Skip to footer

Why Does Delete Keep Array Elements?

Today I stumbled upon a question here on Stack Overflow - How do I remove objects from a javascript associative array?. What struck me was that the accepted answer was both mislead

Solution 1:

I realized I have no idea as to why it makes sense for delete to assign undefined instead of removal.

It doesn't. delete removes properties from objects, it does not set them to undefined. Here's an easy way to tell:

var a = ['a', 'b', 'c'];
console.log(1in a); // logs "true"delete a[1];
console.log(1in a); // logs "false"

Note that after the delete, a doesn't have a property called 1 anymore. At all.

Contrast with:

var a = ['a', 'b', 'c'];
console.log(1in a); // logs "true"
a[1] = undefined;
console.log(1in a); // logs "true"

There, a still has a property called 1, it's just that the property's value is undefined.

It's useful to understand that in JavaScript, arrays aren't really arrays at all. They're just objects, array "indexes" are just property names (which are strings — yes, really, we just tend to write them as numbers), arrays have special handling of property names that are all numeric (indexes), a special length property, and some functions they get from Array.prototype. This is very clearly laid out in Section 15.4 of the spec. Once you have it set firmly in your head that JavaScript arrays aren't really arrays, they make a lot more sense. :-)

Deleting an array "index" property from an array does not change its length (not even if you delete the highest-numbered one); it just creates a hole in the array (JavaScript "arrays" are sparse arrays by their nature; e.g., they can have gaps in them). So in my first example above, I get exactly the same array that I'd've gotten if I'd done this:

var a = [];
a[0] = 'a';
a[2] = 'c';

Note the gap, the array has no 1 element/property.

If you say:

var foo = a[3];

...foo can get the value undefined for two completely different reasons:

  1. a has a property called 3 that has the value undefined, or:
  2. a has no property called 3 at all; the result of a property accessor operation on an object that doesn't have a property by that name is undefined. This if-no-property-return-undefined is covered by the spec in a fairly convoluted way, but mostly in Section 8.12.3.

These are very distinct things.

Solution 2:

It doesn't assign undefined. It deletes the property. (If you try to access a property that doesn't exist, you will get undefined, and length is based on the highest numbered item in the array).

It makes sense, because it works that way on any kind of object. For it to act otherwise, it would have to special case objects if they were an instanceof Array but only if it was a property with a numeric name.

Use splice if you want to remove an item from an array.

> var elements =[NaN,NaN,NaN];
> elements.splice(1,1);
> console.log(elements);
[NaN,NaN]

Solution 3:

JavaScript arrays can be "sparse". That is, some slots can be empty in the sense of never having had a value assigned, or having a value deleted. If you test the value associated with that index you'll get back undefined because it doesn't exist, not because it was assigned the value undefined.

When delete removes an item from an array it doesn't automatically slide the rest of the elements up to fill the space: the other elements retain their existing indexes, which in turn means the .length property doesn't change since .length is defined as being equal to the highest assigned index plus one.

If you want to remove an array element and have the other elements renumbered use the .splice() method.

Solution 4:

This is because delete operator removes property, and removed property has value undefined. To remove element from array you can use splice method of array. All of this is because of how the delete operator in javascript work.

When you do not set property of object and try to check its value it will be undefined:

var obj = {};
alert(obj.foo); // undefined

which is the same as:

alert(obj['foo']); // undefined

And look at this:

// create empty objectvar obj = {};
// check its property named 1
alert(obj[1]); // undefined// set property named 1 to value 'fooo'
obj[1] = 'fooo';
// and check it
alert(obj[1]); // 'fooo'// now delete it delete obj[1];
// and check again
alert(obj[1]); // undefined 

delete has removed property and its value is undefined - and all above code was about object.

Now look at the arrays:

var arr = []; // it's better to use [] than new Array();
alert(arr[1]); // undefined  - same as above// assign value
arr[1] = 'fooo'// check it
alert(arr[1]); // 'fooo' - same as above// remove it delete arr[0];
// and check
alert(arr[1]); // undefined - same as above

So behavior is the same, but what about length property of array. Specification http://es5.github.com/#x15.4.5.2 says:

"The length property of this Array object is a data property whose value is always numerically greater than the name of every deletable property whose name is an array index."

So when you look at this:

var arr = ['foo', 'bar', 'foobar'];
alert(arr.length); // 3// delete firstdelete arr[1]; 
// and check length
alert(arr.length); // 3

Last check gives 3 because the last deletable property in this array has index 2 - first property (with index 0) has value undefined (delete operator set this value), second item (with index 1) has value 'bar' and third (with index 2) has value 'foobar'. So according to specification length = 2 + 1 ('allways numerically greater than last deletable');

This is visible also in this code:

var arr = [];

arr[10] = 'foo';
// element with index 10 is set to 'foo' but elements from 0 to 9 don't have value - they are undefined// now check length
alert(arr.lenght); // 11 

Last deletable property index is 10, so 10 + 1 gives 11, despite of previous elements that are undefined.

So delete operator does his work, but it is not designed to remove items from array.

Post a Comment for "Why Does Delete Keep Array Elements?"