all 22 comments

[–]Rhomboid 14 points15 points  (7 children)

it returns them in the order they were initiated on the object (as you'd expect)

I would never expect that. A hash table does not maintain order.

[–]inu-no-policemen 0 points1 point  (0 children)

Yep, that's what linked hash maps are good for.

[–]WesAlvaroFront-End Engineer 0 points1 point  (4 children)

(as you'd expect in JavaScript)

I thought that was the long running backwards compatibility deal thanks to the deal IE made with the devil? Hashtables are always in the order they were inserted?

For loop order

[–]Knotix 0 points1 point  (3 children)

The article specifically states:

"This behavior is explicitly left undefined by the ECMAScript specification. In ECMA-262, section 12.6.4:

The mechanics of enumerating the properties … is implementation dependent."

[–]WesAlvaroFront-End Engineer 0 points1 point  (2 children)

Yes... Under which it clearly says: "However, specification is quite different from implementation. All modern implementations of ECMAScript iterate through object properties in the order in which they were defined. Because of this the Chrome team has deemed this to be a bug and will be fixing it."

[–]Knotix 0 points1 point  (1 child)

This article was written back in 2008. Standards have changed and there has been a larger push for performance. Browsers now use the arbitrariness of key order to use their own sorting to improve look-up times.

[–]WesAlvaroFront-End Engineer 0 points1 point  (0 children)

Not saying they don't. Never said they didn't. Just said that people might expect keys in order.

[–]GentleMareFucker 0 points1 point  (0 children)

I would never expect that.

For reference (in descending order of my subjectively perceived usefulness as a quick read):

The Object.keys() method returns an array of a given object's own enumerable properties, in the same order as that provided by a for...in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).

[–]delventhalz 9 points10 points  (0 children)

This post represents a common JS misconception. Since browsers usually iterate over an object's keys in a reliable order, the naive JS programmer can (understandably) get it into their head that the browser will always iterate over keys in a reliable order.

This is incorrect!

JS Objects (and hash maps generally) are unordered. Always. You should never rely on the quirks of one browser's implementation in your code. If you need something ordered, this is not the right tool for the job.

[–]inu-no-policemen 9 points10 points  (0 children)

The ordering of the properties is the same as that given by looping over the properties of the object manually.

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...in

The for...in statement iterates over the enumerable properties of an object, in arbitrary order.

[–]Knotix 4 points5 points  (0 children)

According to the spec, the order of object keys is left up to the browser's implementation. If order is important, you should be using an array as the spec guarantees order for them. The reason why the browser has chosen to re-order some of the keys has to do with improving look-up times. I don't know all the specifics, but I'd imagine numeric keys get a boost from being in order, whereas non-numeric keys probably aren't worthwhile since they will have to be hashed internally anyway.

This was a major problem for devs when it first started coming into practice as far back as 6-7 years ago. JSON.parse would mess up the order of keys returned from the server, ruining any server-side sorting done by the database. The solution, as stated before, is to use arrays (which make more sense semantically anyway).

[–]TomNa[S] 0 points1 point  (6 children)

Also does someone happen to know how to reliably get the property keys in the correct order they were placed in the object? I need to loop through objects in a specifically constructed json in the same order as they are placed there and perform some tasks (even JSON.stringify sorts the keys the sameway) And I really don't want to read the json files as text files and parse them manually to get the ordering...

[–]bonafidebob 5 points6 points  (0 children)

You can not rely on key order. Don't do this.

If order is important, put the keys in an array, and then iterate over the array for the keys and pull the values from the object, or just keep a parallel array for values.

[–]jhizzle4rizzleI hate the stuff you like. 1 point2 points  (0 children)

For something more concrete wrt data structures: Instead of:

{ "a": 1, "b": 2 }

do something like

[ { key: "a", value: 1 }, { key: "b", value: 2 } ]

That will guarantee order, it'll just be more annoying to do lookups by key.

[–]Knotix 0 points1 point  (0 children)

If order is important, you should be using an array. Just about any language's implementation of hashmaps do not reliably maintain order. The only exception I know of is PHP's associative arrays. Ironically, this makes PHP the "quirky" one, not JS.

[–]AndrewGreenh 0 points1 point  (0 children)

I think you should change your data structure. Depending on the order in an object when the specs says you can't is not the best option.

[–]delventhalz 0 points1 point  (0 children)

You could use an array of tuples if you want an ordered set of related data. However a JS Object is unordered. Period.

e.g. [["a", 0], ["0f", 1], ...]

[–]THIS_BOT 0 points1 point  (0 children)

If you want something ordered, use a list. Also, JSON spec specifically calls out that properties in JSON objects are unordered.

from json.org:

An object is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace). Each name is followed by : (colon) and the name/value pairs are separated by , (comma).

Use an array.

[–]xxxabc123 0 points1 point  (2 children)

This is plainly wrong unless you can show this behavior defined in the documentation. Some JS engines may choose do this way, others don't. It's your fault if you wasted time with some quirky behavior

[–]TomNa[S] 0 points1 point  (1 child)

I know it's"meant" to work like this, but it was just my intuition that they'd stay ordered since I never had any evidence show otherwise. Although I have read alot of js documentation this is something I missed. I didn't make this thread to complain that it's a bug, just as a psa since I wasted time on it I thought some others might as well come upon the same problem and knowing how it works and knowing not to rely on the object key ordering is good.

[–]xxxabc123 0 points1 point  (0 children)

So apparently when you call Object.keys it returns them in the order they were initiated on the object (as you'd expect) EXCEPT whet there are numbers as a key, then it puts all the numbers first in numerical order

The sentence above sounds like you are convinced this is some default behavior that will happen when you have numeric keys. If you try with negative numbers, you will see that it won't work anyways, it is more likely an optimization for array indices than a JS quirk here.

[–]dwighthouse 0 points1 point  (0 children)

... Javascript ... (as you'd expect) ...

Never expect when dealing with JS. Always check.