Reputation: 348
I was reading though Javascript, the definitive guide and came across a paragraph which said and I quote
If you index an array with a string that happens to be a non-negative integer,it behaves as an array index not an object property
So something like a["4"]
would be stored at an index of 5, whereas something like a["-1.26"]
would be stored as a property "1.26"
..
I got a little adventurous and tried a["02"] = 2;
Now I can set it, retrieve it but it's neither set as a[2]
(basically a[parseInt("02")]
) , nor can I get it when I print the array ..
Here is my code. I tried it with node and the browser.
> a[3] = 3;
3
> a["-1.2"] = 10;
10
> a
[ , , , 3, '-1.2': 10 ]
> a["02"] = 2;
2
> a
[ , , , 3, '-1.2': 10 ]
> a["02"]
2
> a.length
4
I just want to understand what exactly is happening.
Upvotes: 3
Views: 183
Reputation: 140236
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 2^32-1.
So the book is misleading, as it needs to be exactly an integer, no leading zeroes etc.
So "02"
is treated like "hellokitty"
- not an indexed property in any sense.
Consider :
var P = "02"
console.log( ( P ) === ( ( +P >>> 0 ).toString() ) );
//false
var P = "2"
console.log( ( P ) === ( ( +P >>> 0 ).toString() ) );
//true
Here's a function
function isStringConsideredArrayIndex( P ) {
if( typeof P !== "string" ) throw new Error( "strings only" );
return ( (P >>> 0).toString() ) === P &&
( P >>> 0 ) !== ( Math.pow( 2, 32 ) - 1 );
}
Upvotes: 3
Reputation: 46339
The main thing to know is that your "array" is actually more of a map (with some exceptions);
a = {}; // a is an empty object
a['02'] = 'foo';
a['2'] = 'bar';
console.log( a ); // { '02': 'foo', '2': 'bar' }
The same applies if a
is an array, except that the way it's being printed may be different. For example, Google Chrome will only print the array-like keys of an array object (so in this case you would see [undefined, undefined, 'bar']
. It still has the other properties, but its "printing function" for want of a better term is only displaying the array-like ones.
And there are other differences. Arrays have certain properties, such as length
(which will be equal to the largest numeric index which you have defined + 1), and various manipulation functions ('pop', 'join', etc.).
As has been pointed out, an index is considered number-like if it can be converted to an unsigned integer losslessly. i.e. "2" -> 2 -> "2"
loses nothing, whereas "02" -> 2 -> "2"
loses the leading 0
.
To see a full list of everything which is in an object or array, you can use this (which will show your missing "02" key):
for(var i in a){
console.log(i,a[i])
}
Upvotes: 1
Reputation: 3774
Iternally, JavaScript will run the following function on array indexes before they are set :
function ToUint32(x) {
return x >>> 0;
}
So, only numbers or strings that are numbers are valid Array indexes.
Indexes also have to be in the following range [0, 2^32−1].
If one a string isn't a number, it defaults back to object keys.
Upvotes: 0