Take the 2-minute tour ×

I was trying to stringify an array-like object that was declared as an array object and found that JSON.stringify wasn't processing correctly array-like object when it is defined as an array object.

See below for more clarity, --> jsFiddle

var simpleArray = []; //note that it is defined as Array Object 

alert(typeof simpleArray); // returns object -> Array Object

simpleArray ['test1'] = 'test 1';
simpleArray ['test2'] = 'test 2';

alert(JSON.stringify(simpleArray)); //returns [] 

It worked fine and returned me {"test1":"test 1","test2":"test 2"} when I changed

var simpleArray = []; to var simpleArray = {};.

Can someone shed some light or some reference where I can read more?


Question: When typeof simpleArray = [] and simpleArray = {} returned object, why JSON.stringify wasn't able to return {"test1":"test 1","test2":"test 2"} in both cases?

share|improve this question

7 Answers 7

up vote 2 down vote accepted

You don't want an array. When you want an "associative array" in JavaScript, you really want an object, {}.

You can distinguish them with instanceof Array:

[] instanceof Array // true
({}) instanceof Array // false

EDIT: it can process it. It serializes all of the elements of the array. However, to be an element, there must be a numeric key. In this case, there are none.

This is nothing unique to JSON. It's consistent with toSource and the length property.

share|improve this answer
I understand that part, what I wanted to know is why JSON.stringify couldn't process when declared as []. –  Vega Feb 7 '12 at 21:46
Thank you!. I was looking for instanceof. I was trying to use typeof which was returning object in both the cases. –  Vega Feb 7 '12 at 21:53
Since ES 5 there is also Array.isArray(...) ( which by contrast is frame-safe. It can be emulated. –  PointedEars Feb 7 '12 at 22:14

The difference is the indexes. When you use an array [] the indexes can only be positive integers.

So the following is wrong:

var array = [ ];
array['test1'] = 'test 1';
array['test2'] = 'test 2';

because test1 and test2 are not integers. In order to fix it you need to use integer based indexes:

var array = [ ];
array[0] = 'test 1';
array[1] = 'test 2';

or if you declare a javascript object then the properties can be any strings:

var array = { };
array['test1'] = 'test 1';
array['test2'] = 'test 2';

which is equivalent to:

var array = { };
array.test1 = 'test 1';
array.test2 = 'test 2';
share|improve this answer
So what happens when you do var simpleArray = []; simpleArray ['test2'] = 'test 2';? –  Matt Fenwick Feb 7 '12 at 21:43
@MattFenwick, what happens is that contrary to what you might expect: simpleArray.length = 0 which means that there are no elements in this array. You could still use simpleArray.test2 to access the property you have defined. It's just confusing code that should be avoided. –  Darin Dimitrov Feb 7 '12 at 21:45
+1 for the detailed explanation but, what I wanted to know is why JSON.stringify couldn't process when declared as []. I tried to use typeof and it returned me object in both cases. I am going to add this to my question. –  Vega Feb 7 '12 at 21:51
@SKS, you have declared simpleArray as array - []. This means that you need to use integer based indexes. In your example you haven't. So in this case simpleArray.length = 0, it's as if this array didn't contain any elements. So it's perfectly normal that the JSON.stringify method will serialize this empty array to []. You just violated the rule that arrays must have integer based indexes and bad things happen when you violate rules. –  Darin Dimitrov Feb 7 '12 at 21:56
I was able to figure out that much, but then was wondering when typeof was returning object and why JSON.stringify wasn't able to process. Now I clearly understand that it detects as an Array using if (Object.prototype.toString.apply(value) === '[object Array]') { and iterates thru length which is 0 and so the result is []. Thanks Again. –  Vega Feb 7 '12 at 22:09

"Can someone shed some light or some reference where I can read more?"

When you're dealing with JSON data, you can refer to json.org to read about the requirements of the specification.

In JSON, an Array is an order list of values separated by ,.

enter image description here

So the JSON.stringify() is simply ignoring anything that couldn't be represented as a simple ordered list.

So if you do...

var simpleArray = [];
simpleArray.foo = 'bar';

...you're still giving an Array, so it is expecting only numeric indices, and ignoring anything else.

Because JSON is language independent, the methods for working with JSON need to make a decision about which language structure is the best fit for each JSON structure.

So JSON has the following structures...

{} // object
[] // array

You should note that though the look very similar to JavaScript objects and arrays, they're not strictly the same.

Any JavaScript structures used to create JSON structures must conform to what the JSON structures will allow. This is why the non-numeric properties are removed excluded.

While JavaScript doesn't mind them, JSON won't tolerate them.

share|improve this answer
Non-numeric properties (better: properties with non-numeric name) are not removed. They are not considered for iteration in the first place. –  PointedEars Feb 7 '12 at 22:25
@PointedEars: That was poor wording. I meant removed as a matter of perspective of the developer, as in "Hey, they're in my Array object, but not in my JSON text!". I should have said "excluded". –  squint Feb 7 '12 at 22:37

When JSON.stringify encounters an array, it iterates in a similar way to a for loop from 0 to simpleArray.length to find the values. For example:

var a = [];
a[5] = "abc";
alert(JSON.stringify(a)); // alerts [null,null,null,null,null,"abc"]

Therefore setting properties on it will be completely invisible to JSON.

However defining the object with {} makes JSON treat it as an object, and therefore it loops over the object's properties (excluding inherited properties from the prototype chain). In this manner it can find your test1 and test2 properties, and successfully returns what you expect.

share|improve this answer

The differences between Array instances and other objects are specified in the ECMAScript Language Specification, Edition 5.1, section 15.4.

You will find there that while you can use the bracket property accessor syntax with all object references --


-- Array instances are special. Only using a parameter value which string representation is that of an unsigned 32-bit integer value less than 232-1 accesses an element of the encapsulated array structure, and write access affects the value of the Array instance's length property.

Section 15.12 specifies the JSON object and its stringify method accordingly.

share|improve this answer

In Javascript, everything is an object, so even Arrays. This is why you get:

>> var l = [1, 2];
>> typeof l

Arrays are stored the same way as objects. So, in fact, arrays are only hashtable objects. The index you provide when accessing e.g.

>> l[0]

is not interpreted as an offset, but is hashed and then searched for.

So Arrays, are just objects (with some builtin array-methods) and so you can treat them like objects and put a value under a certain key. But only those keys indexed by numbers are used to compute the length.

>> var l = []
>> l.length
>> l[5] = 1;
>> l.length
>> l
[undefined, undefined, undefined, undefined, undefined, 1]
>> l.hello = "Hello"
>> l.length

Read Array - MDN for more information and Associative Arrays considered harmful why you should not do this.

share|improve this answer
Not everything is an object. There are primitive values. But there is no "Javascript", there are several different ECMAScript implementations. –  PointedEars Feb 7 '12 at 22:02

Your code is not semantically correct, but because most JavaScript engines are really nice on the programmer they allow these types of mistakes.

A quick test case:

var a = [];
a.b = "c";
console.log(JSON.stringify(a));//yields [], and not {"b":"c"} as you might expect

This might be because of some strictness in JSON.stringify which still treats a like an Array. I wouldn't worry about it overly much. This is a situation that should not occur in your program because it is an error. JSLint is a popular tool to catch these and many more potential problems in your code.

share|improve this answer
Pray tell, what is wrong with the syntax? –  PointedEars Feb 7 '12 at 22:00
I thought it was rather obvious: you can't declare string keys in Arrays. Just because most JavaScript engines accept it doesn't make it correct. I hope you thought the down-vote was worth it. –  Halcyon Feb 7 '12 at 22:46
You have serious misconceptions as to the nature of JavaScript, of ECMAScript objects, and what belongs to the syntax of a programming language. One comment is to short for that. There are no keys. Objects have properties with names. Property names are strings, accessed with [], ., or implicitly (scope chain). JavaScript is an ECMAScript implementation. Of JavaScript there are only two production-quality "implementations": SpiderMonkey and Rhino; others like JScript are ECMAScript implementations. To be continued … –  PointedEars Feb 8 '12 at 11:15
Array instances are objects. Some property names refer to elements with them, per Specification. Using a "string key" with property access on Array instances may be a semantic error if you want to access an element of the array structure. Think about this: var a = []; a["0"] = "b"; console.log(a["length"], a.length, a, a[0]); /* _syntax_ error _in the following_, because 0 is not an identifier: */ a.0; –  PointedEars Feb 8 '12 at 11:19
You have a strange way of trying to be constructive. You could have simply suggested I change it to "semantically". I suppose what you mean is that a.b = "c" is valid given that a is an ArrayObject. So it is syntactically allowed, because you can assign properties to Objects, but it's semantically wrong because the value "c" will not appear in the Array when you JSON.stringify it. - I don't think arguing about jargon is the right scope. –  Halcyon Feb 8 '12 at 19:37

Your Answer


