3

I have following array:

var arr = [];
console.log(arr.length); //Output: 0

arr["1231321"] = "abcd";
console.log(arr.length); //Output: 1231322

arr["1231321".toString()] = "abcd";
console.log(arr.length); //Output: 1231322

arr["a1231321"] = "abcd";
console.log(arr.length); //Output: 0

arr["1231321a"] = "abcd";
console.log(arr.length); //Output: 0

Here is the Fiddle: http://jsfiddle.net/HcrcR/

when I change my arr to var arr = {}; then it works.

but what is the reason of it even if I use string key it starts pushing the data from key?

Vural
  • 8,666
  • 11
  • 40
  • 57
  • 2
    You have an array. When you use `arr["key"]` (non-numeric keys...strings are still converted), you are setting properties, which have nothing to do with its contents/length – Ian Mar 04 '13 at 22:09
  • This may be relevant http://stackoverflow.com/questions/2693021/how-to-count-javascript-array-objects – user1477388 Mar 04 '13 at 22:09
  • 1
    When you use: var arr = {} you have an object which uses key/value pairs. – Steve Wellens Mar 04 '13 at 22:09

3 Answers3

6

I have following array/hashmap:

That's an Array in JavaScript terms.

var arr = [];
console.log(arr.length); //Output: 0

That's expected, it's an empty array.

arr["1231321"] = "abcd";
console.log(arr.length); //Output: 1231322

The reason the length property is so large as it's always +1 than the highest index. It doesn't matter that you used a string, keys for Arrays and Objects are always strings in JavaScript.

The length property of this Array object is a data property whose value is always numerically greater than the name of every deletable property whose name is an array index.

Source

arr["1231321".toString()] = "abcd";
console.log(arr.length); //Output: 1231322

Calling toString() on a string doesn't do anything (it's already a string).

arr["a1231321"] = "abcd";
console.log(arr.length); //Output: 0

Also expected, you set a property on the Array which doesn't look like an index.

arr["1231321a"] = "abcd";
console.log(arr.length); //Output: 0

See above. There is no parsing internally of the string to try and get a number.

when I change my arr to var arr = {}; then it works.

That's how objects work in JavaScript. They're just a bucket of string keys to values.

alex
  • 479,566
  • 201
  • 878
  • 984
  • then we can say, JS converts string keys to number if possible, when we use array. But when we create an Object, then it keeps the key with the own type – Vural Mar 04 '13 at 22:12
  • 1
    @Vury JavaScript keys are always strings, even for arrays. – alex Mar 04 '13 at 22:13
4

Array != Object (or hashmap) in JavaScript. Therefore, properties added to an array that aren't integer indexes don't affect Array.length

Note that there is not reserving of space, just because the length is 1231321, it doesn't mean that all the spaces are allocated, JavaScript arrays don't have to use contiguous memory, and often don't if they are sparse. In reality, they are only contiguous as an optimization, and the default behavior is that they are hash maps just like objects.

If you need to know all the keys that an object has, you need to use https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys

However, you should not mix both concepts, in JS, you should either be working with an array (numeric indexes) or an object (any indexes)

When you do

arr["1231321"] = "abcd";

That's the same as

arr[1231321] = "abcd";

Which affects the length of the array. However,

arr["1231321a"] = "abcd"

Does not create a new array index (just a new object property) and it doesn't affect the length property

Note that your example in your question is incorrect, if you type the following commands one after the other

arr = [];
arr["1231321"] = "abcd";
console.log(arr.length); //Output: 1231322
arr["a1231321"] = "abcd";
// Output: 1231322, should be the same as before, not undefined
console.log(arr.length); //Output: 1231322

http://jsfiddle.net/tWCa4/

Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • *However, you should not mix both concepts*, glad you mentioned this, very important to stop confusion :) – alex Mar 04 '13 at 22:23
2

It is able to use your first 2 strings as indices, since they are able to be parsed as numbers.

When you pass it something that can't be parsed as an integer, the array will instead attach that as a property of the array, rather than an entry.

When you define it as an object, it will act as an object and treat everything as a string property. Length will always be defined as the highest value+1 for an array in javascript.

So to be clear

var x = [] 

creates a new Array which will try to parse its inputs to integers and add them into the array, but will otherwise assign them as properties.

var x = {}

will create an Object, which works as an unordered set of properties and will not have a length unless you custom define x.length = y in which case it will simply be another property with no special meaning.

Ben McCormick
  • 25,260
  • 12
  • 52
  • 71
  • I didn't downvote but the first line isn't true, there is no casting to numbers. – alex Mar 04 '13 at 22:17
  • Not the downvoter either, but there's no casting to numbers, what `Array` does is to look at all keys, and treats the ones that look like integers as if they were integers – Ruan Mendes Mar 04 '13 at 22:21
  • Yeah casting was not the right term. Thanks for explaining. I don't care about the downvote, I want to be accurate :) Does my update look better? – Ben McCormick Mar 04 '13 at 22:23