Should negative indexes in JavaScript arrays contribute to array length?

Solution 1:

SO for me logically it seems like arr[-1] is also a part of arr.

Yes it is, but not in the way you think it is.

You can assign arbitrary properties to an array (just like any other Object in JavaScript), which is what you're doing when you "index" the array at -1 and assign a value. Since this is not a member of the array and just an arbitrary property, you should not expect length to consider that property.

In other words, the following code does the same thing:

​var arr = [1, 2, 3];

​arr.cookies = 4;

alert(arr.length) // 3;

Solution 2:

The length property will return a number one higher than the highest assigned "index", where Array "indexes" are integers greater than or equal to zero. Note that JS allows "sparse" arrays:

var someArray = [];
someArray[10] = "whatever";
console.log(someArray.length); // "11"

Of course if there are no elements then length is 0. Note also that the length doesn't get updated if you use delete to remove the highest element.

But arrays are objects, so you can assign properties with other arbitrary property names including negative numbers or fractions:

someArray[-1] = "A property";
someArray[3.1415] = "Vaguely Pi";
someArray["test"] = "Whatever";

Note that behind the scenes JS converts the property names to strings even when you supply a number like -1. (The positive integer indexes also become strings, for that matter.)

Array methods, like .pop(), .slice(), etc., only work on the zero-or-higher integer "indexes", not on other properties, so length is consistent on that point.

Solution 3:

Note that when you use a position (or 0) index, values are placed within the array:

var array = [];

array[0] = "Foo";
array[1] = "Bar";

// Result: ["Foo", "Bar"]
// Length: 2

This is not the case when you add non-index values (not 0-9+):

var array = [];

array[0]  = "Foo";
array[1]  = "Bar";
array[-1] = "Fizzbuzz"; // Not a proper array index - kill it

// Result: ["Foo", "Bar"]
// Length: 2

Values are only placed in the array when you play by the rules. When you don't, they aren't accepted. They are however accepted on the Array object itself, which is the case with just about anything in JavaScript. Even though ["Foo", "Bar"] are the only values in our array, we can still access "Fizzbuzz":

array[-1]; // "Fizzbuzz"

But note again that this isn't part of the array values, since its "index" isn't valid. It was instead added onto the array as just another member. We could access other array members in the same fashion:

array["pop"]; // function pop() { [native code] }

Note here that we're accessing the pop method on the array, which informs us that this contains native code. We're not accessing any of the array values with a key of "pop", but rather a member on the array object itself. We can further confirm this by cycling over the public members of the object:

for (var prop in array) 
    console.log(prop, array[prop]);

Which spits out the following:

 0 Foo
 1 Bar
-1 Fizzbuzz

So again, it's on the object, but it's not in the array.

Awesome question! Caused me to do a double-take for sure.