akanksha1105
akanksha1105

Reputation: 348

How does a javascript array store keys such as "02"

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

Answers (3)

Esailija
Esailija

Reputation: 140236

From specs

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

Dave
Dave

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

m_vdbeek
m_vdbeek

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

Related Questions