6

In many languages, the standard dynamic list (not fixed-size array) type will resize after an item is deleted:

Python:

myList = ['a', 'b', 'c']
del(myList[0])
print(len(myList)) # Prints '2'

C#:

var myList = new List<string> {"a", "b", "c"};
myList.RemoveAt(0);
Console.WriteLine(myList.Count); // Prints '2'

and so on.

However, in Javascript, the list length stays the same, even though the element evaluates to undefined (this tells me that it's different to array[index] = undefined):

Javascript:

var myArray = ['a', 'b', 'c']
delete myArray[0]
console.log(myArray.length) // Prints '3'
console.log(myArray) // Prints "[ , 'b', 'c' ]" in node, '[undefined × 1, "b", "c"]' in Chrome

myArray[0] = undefined
console.log(myArray) // Prints "[ undefined, 'b', 'c' ]" on both node and Chrome

myArray.splice(0, 1)
console.log(myArray) // Prints "['b', 'c']"

My questions are:

  • Is the JS array delete behaviour by design or an oversight that couldn't be fixed for fear of breaking legacy code?
  • What exactly is the 'undefined-like' value that replaces the deleted array element?
svbnet
  • 1,070
  • 3
  • 11
  • 29
  • *(I should have realized this was a duplicate. That dupetarget goes on my list for next time... :-) )* – T.J. Crowder Feb 19 '17 at 10:22
  • In JavaScript the `delete` instruction is not array specific. It's an instruction that you can use on all JS objects to delete a specific property. It means `delete` doesn't delete an item in an array but deletes the key (array object's property) and turns the array into a sparse one. In JS this is the only way to turn a dense array into a sparse one by removing an item. So it's valuable. – Redu Feb 19 '17 at 10:25
  • an undefined slot has the value of undefined, but hasOwnProperty will reveal all. rememember that object keys don't vouch for object values, one of which can be _undefined_, which is the same "return" as asking for a non-existing property. – dandavis Feb 19 '17 at 10:35

2 Answers2

4

Your comparison of delete to RemoveAt and such is incorrect. delete doesn't do what they do; to do that, you'd use splice:

var myArray = ['a', 'b', 'c']
myArray.splice(0, 1);
console.log(myArray.length) // Prints '2'

delete removes the entry without reordering other entries, creating a sparse array (an array with some entries missing entirely). delete isn't really meant for arrays, it's meant for removing properties from objects; but it applies to arrays because standard (e.g., non-typed) arrays in JavaScript aren't really arrays at all*, they're objects with special handling for certain properties, such as those whose names are "array indexes" (which are defined as string names "...whose numeric value i is in the range +0 ≤ i < 2^32-1") and length.

length's value is changed if you:

  • Use any method to add or remove entries (splice, push, etc.).
  • Add an entry by assigning to an index equal to or greater than length.
  • Assign directly to length: If you increase length, you make the array sparse; if you decrease it, you remove any entries at that index or above. E.g., if you have an array ['a', 'b', 'c', 'd', 'e'] and do theArray.length = 3, it won't have entries at indexes 3 ('d') or 4 ('e') anymore.

Is the JS array delete behaviour by design or an oversight that couldn't be fixed for fear of breaking legacy code?

By design. As mentioned above, delete is primarily about removing properties from objects.

What exactly is the 'undefined-like' value that replaces the deleted array element

There isn't one. This is another by-product of the fact standard arrays are objects: If you try to read the value of a property from an object that it doesn't have, the result of that "get" operation is the value undefined. It's not that there's something in the object with an undefined-like value, it's that there's no property in that object with that name at all. This illustration may be useful:

var o = {}; // A non-array object
console.log(o.noSuchProperty);    // undefined
console.log(o["noSuchProperty"]); // undefined
console.log(o[2]);                // undefined

var a = []; // An array object
console.log(a.noSuchProperty);    // undefined
console.log(a["noSuchProperty"]); // undefined
console.log(a[2]);                // undefined

* (that's a post on my anemic little blog)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Ah, interesting! I was confusing the REPL representation of the array with its actual value, since the Chrome output at least implies there's something to do with `undefined`, when in reality it's just telling you there's nothing there. I also didn't know that `length` was settable, so thanks for that. – svbnet Feb 19 '17 at 11:33
1

This seems to be a duplicate of: deleting-array-elements-in-javascript-delete-vs-splice

As you mentioned using delete will not remove the element, but instead just set it to undefined. Splice, unshift or pop however, will remove that block from the array.

CWright
  • 2,068
  • 2
  • 16
  • 20
  • 1
    "but instead just set it to undefined" --- that's not technically correct. When a property is deleted - it's deleted. Setting it to `undefined` is different to that. – zerkms Feb 19 '17 at 10:12
  • an undefined slot has the value of _undefined_, bur `hasOwnProperty` will reveal all – dandavis Feb 19 '17 at 10:28