3

I have the following code that outputs the length of an array, deletes it, and then outputs the new length:

console.log($scope.adviceList.activeAdvices.length); // *1*
$scope.adviceList.activeAdvices.splice(id,1); // *id is a parameter*
console.log($scope.adviceList.activeAdvices.length); // *0*

console.log($scope.adviceList.activeAdvices.length); // *1*
delete $scope.adviceList.activeAdvices[id];
console.log($scope.adviceList.activeAdvices.length); // *0*
console.log($scope.adviceList.activeAdvices); // *[]*

After the deletion, the array is correctly displayed as empty. Its length, however, is still 1.

Wottensprels
  • 3,307
  • 2
  • 29
  • 38
  • Where are these variables declared? – me_digvijay Aug 23 '13 at 06:59
  • 1
    See first answer in http://stackoverflow.com/questions/500606/javascript-array-delete-elements – tsiki Aug 23 '13 at 07:00
  • 1
    possible duplicate of [Javascript object with array, deleting does it actually remove the item?](http://stackoverflow.com/questions/495764/javascript-object-with-array-deleting-does-it-actually-remove-the-item) – tsiki Aug 23 '13 at 07:03
  • why the length is zero after you spliced id to the array? – Burak Keceli Aug 23 '13 at 07:04
  • @B.K. the array held only that element – Wottensprels Aug 23 '13 at 07:05
  • @B.K.: `.splice` does not only add elements, it also removes them. In this case it removes one element. – Felix Kling Aug 23 '13 at 07:05
  • 1
    `delete` is a "lower" level operator. It directly works on the object, it doesn't "know" about the array. Using `delete` simply doesn't trigger the routine to recompute the array length. – Felix Kling Aug 23 '13 at 07:11
  • 1
    *"delete won't actually delete the item, but rather set it to undefined"* That's incorrect. The property is removed. Try `var a = [1]; delete a[0]; console.dir(a);` – Felix Kling Aug 23 '13 at 07:12
  • You really shouldn't edit the answer into your question. The answer already appears below the question, indicated with a green checkmark. The question should remain...the question. – Cody Gray - on strike Aug 23 '13 at 07:52

5 Answers5

11

delete is a "lower level" operator. It directly works on the object, it doesn't "know" about the array. Using delete simply doesn't trigger the routine to recompute the array length.


Other answers here claim that the value of the property is set to undfined, which is incorrect. A simple test shows that:

var a = [1]; 
delete a[0]; 
console.dir(a);

and compare to what happens if you really set the value to undefined:

var a = [1]; 
a[0] = undefined; 
console.dir(a);

For a more solid proof, lets have a look at the specification:

When the [[Delete]] internal method of O is called with property name P and the Boolean flag Throw, the following steps are taken:

  1. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with property name P.
  2. If desc is undefined, then return true.
  3. If desc.[[Configurable]] is true, then
       a. Remove the own property with name P from O.
       b. Return true.
  4. Else if Throw, then throw a TypeError exception.
  5. Return false.

Nowhere it is said that the value of the property is set to undefined.


The consoles of different browsers might show different representations of the array. In this particular example, you can argue whether it should be [] or [undefined].

  • [] (Chrome) seems to make sense because the array really doesn't have any elements, there are no properties with numeric names. However, when you access the .length property, you would get a 1, which can be confusing.
    Not too long ago, Chrome used a representation like [undefined x 5] to indicate an array of length 5 but without elements. I think this was actually a good solution.

  • [undefined] (Firefox) makes sense because the array is of length 1 and accessing arr[0] actually returns undefined (but so does arr[10]).However, arr.hasOwnProperty(0) would be false and if an array really contains the value undefined, how can it be distinguished from an empty array of length one solely by this representation (answer: you can't).

The bottom line is: Don't trust console.log too much. Rather use console.dir if you want an exact representation.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
2

It's because delete on array element set it to undefined so the length don't change. Use splice function instead:

a = [1,2,3,4];
a.splice(2,1);
console.log(a.length);
jcubic
  • 61,973
  • 54
  • 229
  • 402
1

if you want "delete" a item in array,you could

var a = ["a","b"];
console.log(a);  //a,b
console.log(a.length);//2
a.length = 1;//"delete" all greater than length 1 of items;
console.log(a);//a
console.log(a.length);//1

or

 var a = ["a","b"];
    console.log(a);  //a,b
    console.log(a.length);//2
    a.pop();//"delete" the last in array:"b"
    console.log(a);//a
    console.log(a.length);//1

or

 var a = ["a","b"];
    console.log(a);  //a,b
    console.log(a.length);//2
    a.shift();//"delete" the first in array:"a"
    console.log(a);//b
    console.log(a.length);//1

or

 var a = ["a","b"];
    console.log(a);  //a,b
    console.log(a.length);//2
    a.splice(1,1);//"delete" from index 1(include,first parameter),delete number is 1(second parameter)
    console.log(a);//a
    console.log(a.length);//1
王奕然
  • 3,891
  • 6
  • 41
  • 62
0

For my part, I redefined the length after delete:

var cars = ["BMW", "Volvo", "Saab", "Ford"];
delete cars[1];

/// 1st option ///
for (var i = 0; i < cars.length; i++){
  if(i in cars)
    document.write(cars[i] + " ");
}
/// return: BMW Saab Ford

/// 2nd option ///
cars.length--;
var realLength = cars.length;
pmrotule
  • 9,065
  • 4
  • 50
  • 58
0

I created a new array and pushed elements on it to get the right length. For example, I had this for table headers:

 var finalTableHeaderArray = [];

 tableHeaderArray.forEach(function (element, index, array) {
    if (removeDisplayItems.indexOf(index) === -1)
        finalTableHeaderArray.push(element);
 }, self);

Not exactly your question, but it could help others.

johnny
  • 19,272
  • 52
  • 157
  • 259