Ben Aston
Ben Aston

Reputation: 55759

Why do string indices (albeit representing integers) work in arrays?

Why does the following enumerate correctly?

var arr = [];
arr[0] = 'foo';
arr['1'] = 'bar';

arr.forEach(v => console.log(v)); // foo, bar

Both arr[1] and arr['1'] also work. Is this a feature of Array that strings corresponding to integers are mapped to their integer value?

Upvotes: 4

Views: 60

Answers (3)

Danield
Danield

Reputation: 125561

Is this a feature of Array that strings corresponding to integers are mapped to their integer value?

No. Think of Arrays just like regular objects.

When accessing a property of an object using bracket notation - the property must be quoted.

eg: var someVar = { a:1, b:2 } - to access the value of property 'a' with bracket notation we write: someVar['a']

So it makes perfect sense to access array elements via quoted indexes.

That being said, it isn't necessary to quote the index - and that's because - as others have mentioned - the index is coerced into a string by the JavaScript engine through an implicit toString conversion

Upvotes: 1

Lennholm
Lennholm

Reputation: 7480

It's due to the fact that arrays in Javascript are just objects with some dedicated syntactic sugar.

Compare:

var arr = [];
arr[0] = 'foo';
arr['1'] = 'bar';
console.log(arr['0']);
console.log(arr[1]);

... to:

var obj = {};
obj[0] = 'foo';
obj['1'] = 'bar';
console.log(obj['0']);
console.log(obj[1]);

Basically, Array is a type of Object, with array specific methods and non-enumerable properties, such as length, which can be instantiated with the dedicated shorthand syntax [ items... ]

The indices of an array are actually strings, just like all keys in any object, it works because referencing an object property using a number as a key will coerce that number into its string representation (in principle, that is. I assume most modern browsers have internally optimized this heavily).

Example:

var obj = {};
obj[1.5] = 'foo';
console.log('1.5' in obj);
console.log(obj[1.5]);

var arr = [];
arr[0.5] = 'foo';
console.log('0.5' in arr);
console.log(arr[0.5]);

arr[0] = 'bar';
arr[1] = 'baz';
console.log(arr.length);
console.log(Object.keys(arr));

Upvotes: 2

SVSchmidt
SVSchmidt

Reputation: 6557

For those questions, It may be worth taking a look into the specification

Array objects give special treatment to a certain class of property names. 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

Thus, because:

parseInt("1").toString() === "1"

"1" is a perfectly valid array index.

See http://www.ecma-international.org/ecma-262/5.1/#sec-15.4

EDIT: One might ask "What's with 1 (a number)", because parseInt(1).toString() is not equal to 1 (but "1", a string). I think the answer to this is the part "(in the form of a String value)", so I believe 1 is first interpreted as "1" before applying those rules.

Upvotes: 1

Related Questions