This post is regrettably a little late, since I felt the need to figure out how to implement a pull-down menu system based on CSS as a poster mentioned in an earlier thread (it now works beautifully, btw). But I felt the need to comment on this behavior, since it is understandably a little confusing.
If you delete an array key directly with the delete command, eg: `delete myArray[4];` the length property doesn't get updated even though the number of elements in the array does. (WTF?!?!)
This statement is a bit inaccurate, but the behavior that occurs makes sense once you realize that all objects in JavaScript (including arrays and functions) are really associative arrays--they are not conventional arrays like you would find in C and Java. As far as JavaScript is concerned, an array is just 1) an extended object with 2) a special literal syntax, 3) which accepts unsigned integers as member names (though you cannot use the dot syntax to select them) and 4) which has a length property that automatically updates when you do something with the object (as opposed to doing something to the object, which is what the delete operator does), In order to remove an index from an array and have it reflected in the length property you have to use an array method (shift, pop, or splice, depending upon whether you're removing items from the beginning, end, or middle of the array, respectively). In JavaScript, the delete operator is only used to deallocate hash keys from an object and remove links for garbage collection; and since myArray [4] is not really the fourth element of the array, but a property with a name whose value is not a string, it doesn't invoke any special array behaviors, as an array method would. The array's length property is just a hook to allow programmers loop through the construct using a conventional for loop without needing a sizeof operator (which wouldn't work that well, anyhow; since JavaScript arrays are untyped).
In case anyone is still reading this (and actually cares), the following examples might shed some light on how this works:
var myArray = new Array (10); // Create an uninitialized array with an initial length of ten.
myArray [4] = 20; // Assign a value to index 4 (really just a member with a name of '4')
for (var p in myArray) alert (p); // Loop through the object properties and display each one to the user, in sequence.
delete myArray [4];
for (var p in myArray) alert (p); // Loop through a second time
alert (myArray.length); // Display the length of the array (as understood by the interpreter) to the user.
You'll notice in this example that the first loop only displays one property (4), the second loop never displays anything, and the final length is still ten. If you adjust it to the following:
var myArray = new Array (10); // Create an uninitialized array with an initial length of ten.
myArray [4] = 20; // Assign a value to index 4 (really just a member with a name of '4')
for (var p in myArray) alert (p); // Loop through the object properties and display each one to the user, in sequence.
myArray.splice (4, 1);
for (var p in myArray) alert (p); // Loop through a second time
alert (myArray.length); // Display the length of the array (as understood by JavaScript) to the user.
The output is the same, except that this time around, the length actually changes to 9. This is the correct way to use arrays--the delete operator is a little bit too low-level in JavaScript to work the way you're trying to use it. It's a bit counter-intuitive, but the way JavaScript handles arrays can be useful if you're indexing objects on the client side based upon the table ids assigned by your database system of choice (assuming that you use some sort of integer-based record id scheme and none of your screens ever display too many items at once), since you need not define any of the intervening indices. This allows for something like the following:
var myArray = new Array ();
myArray [500000] = true;
myArray [1000000] = false;
for (p in myArray) {
if (!isNaN (Number (p))) { // This test is not necessary if your array doesn't contain any custom members, // since only the enumerated keys will be found in the loop // Note that the length property never gets alerted in these examples, except where explicitly requested.
alert (p + ' = ' + myArray [p]);
}
}
This allows you to have an array with an implicit length of one million items (and if you alert the length of myArray using the code in this example, it will output "1000000"), but when you loop through it, there are really only two properties in the object; so you need not waste any CPU cycles on indices that have not yet been defined.
Personally, I think this is a cool behavior, even though I rarely employ it. As a general rule (with some very rare exceptions), my JavaScript code has all variables defined and initialized at the beginning of the function and before execution of any general-purpose logic, since that old-school design philosophy tends to reduce problems further down the road.