Both parts have very clear and unsurprising explanations if you understand how IEEE 754 doubles work (same type as C double). For example, section 15.4 of ES5:
> A property name P (in the form of a String value) is an array index if and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal to 232−1.
.
-1 is the easier case to understand: ToUint32(-1) is 2^32 - 1 and ToString(ToUint32(-1)) is "4294967295", which is very clearly not -1.
Needless to say, the C equivalent is an out-of-bounds dereference.
.
While -0 is technically a different value from 0 (it's called negative zero in IEEE 754), the ToUint32 operation specifically carves out a case:
A) The literal `-0` is interpreted as an integer. The actual value it uses is zero:
char ** foo = (char **)malloc(3 * sizeof(char *));
foo[0] = foo[1] = foo[2] = "foo";
foo[-0]="bar"; /* this sets foo[0] since the compiler treats -0 as the unary negation of the integer 0 and integers have no signed zero */
printf("%d|%s|%s|%s\n", -0, foo[0], foo[1], foo[2]); /* "0|bar|foo|foo" since the -0 is understood by the compiler to be the actual value 0 */
B) Since JS interprets `-0` as an IEEE754 double, the value can be recreated by going through negative infinity:
double ninf = (-1.0/0.0); /* should be -Infinity */
printf("%g\n", ninf); /* "-inf" just to be sure */
double nzero = (1.0 / ninf); /* should be IEEE 754 negative zero */
printf("%g %d %zu\n", nzero, (int)nzero, (size_t)nzero); /* "-0 0 0" -0 behaves like 0 when casted to integer types */
.
The arguably surprising part is that JS doesn't have integer literals, but that isn't surprising when you think about the fact that JS only has one number type which maps to IEEE 754 double.
> The arguably surprising part is that JS doesn't have integer literals, but that isn't surprising when you think about the fact that JS only has one number type which maps to IEEE 754 double.
The fact that people have been able to run cryptography through JavaScript despite it not having integers is pretty amazing. Yes, I know the mantissa is where the bits are stored, but it still amazes me.
a[-0] = "foo";
console.log(a.length);
console.log(a[-0]);
and people complain it's not fun.
On edit - should probably have done this instead
var a = new Array();
a[-0] = "foo";
a[-1] = "foo+";
console.log(a.length);
for(var b = 0; b < a.length; b++){