Selvakumar Arumugam
Selvakumar Arumugam

Reputation: 79850

Javascript Array Object vs Array Like Objects - Clarification

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?

Edit:

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?

Upvotes: 6

Views: 3359

Answers (7)

PointedEars
PointedEars

Reputation: 14980

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 --

objRef[propertyName]

-- 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.

Upvotes: 1

Halcyon
Halcyon

Reputation: 57721

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.

Upvotes: -1

user1106925
user1106925

Reputation:

"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.

Upvotes: 2

Matthew Flaschen
Matthew Flaschen

Reputation: 285077

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.

Upvotes: 2

knub
knub

Reputation: 4032

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

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

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
0
>> l[5] = 1;
>> l.length
6
>> l
[undefined, undefined, undefined, undefined, undefined, 1]
>> l.hello = "Hello"
>> l.length
6

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

Upvotes: 0

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324810

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.

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1039498

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';

Upvotes: 5

Related Questions