Why Does Delete Keep Array Elements?
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:
a
has a property called3
that has the valueundefined
, or:a
has no property called3
at all; the result of a property accessor operation on an object that doesn't have a property by that name isundefined
. 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.
Post a Comment for "Why Does Delete Keep Array Elements?"