I think I might disagree with #3. I find that having arr[-1] point towards the last element of the array can hide accidental off-by-one errors. It's also a bit weird how the arrays are zero-based if you access them normaly but one-based if you access them backwards. IMO it's more consistent to make the negative indexes behave the same way as an out of bounds access like arr[arr.length + 1]
If your mental model is that an array is zero-indexed but circular, I think arr[-1] still is consistent with that model. If you don’t think of arrays as circular, then sure, it doesn’t make sense.
I’m still in agreement that negative indices make it more confusing than just calculating based off the length, but I get why they exist.
The mental model doesn’t really jive with circularity since arr[arr.length] is not the same as arr[0] in any language that I know of. With a circle, you would expect that arr[0], arr[length], and arr[2*length] are all identical.
Certainly negative indexes being out-of-bounds would be the most consistent behaviour, but that requires giving up the index-from-end functionality (or, at least giving up up with the defualt array access syntax).
If you are going to have negative indexing, there isn't really a better alternative than 1 based indexes; since you can't exactly do arr[-0]
I was going to make a comment about this not working for integer types; but then I remembered that JavaScript doesn't have integers, so I guess it technically works.
That code would (assuming an integer value; the question is interesting without reference to the implementation of JavaScript) return arr[0], the first element. Don't think of arr[-1] as indexing the array with a negative number that might have been a positive number. Think of array access from the front, arr[ ], and array access from the back, arr[- ], as separate operations with separate syntax, each of which can accept only nonnegative numbers. arr[i] is of the first type, so you get the first element counted from the front.
Actually, I think that might work in Javascript! All the numbers are IEE754 floating point numbers and there are separate values for positive and negative zero.