Object Order isn’t specified in Javascript (except it is)

Joe Cortopassi
4 min readNov 18, 2016

--

TL;DR: Integer indices in ascending order, followed by string indices in order of creation, then Symbols in creation order as well

Everyone always says that an Object’s property order is not specified, mostly because it wasn’t. If you look back to the spec for ECMAScript 5 and 5.1, you’ll see that it literally says “It is an unordered collection of properties” when talking about keys and enumeration. In practice though, what you ended up seeing is most browsers had a similar and predictable order to their objects. How was this? I’ll deal with that later, but first let’s talk about the guaranteed order of an object in ECMAScript6. But Joe, I’ve read 6.1.7 in the spec, and there’s nothing in there about object order. True, but part of the spec is not just how the object should behave, but also what its internal methods must be consistent with. So while it doesn’t say, “hey keys, line up according to who’s birthday comes first”, there is an internal consistency to it. Should you build applications based on that consistency? Heck no! Not because it’s going to change on you, but rather because it’s goofy and will probably only serve to frustrate anyone who has to maintain your clever code.

Look Joe, it’s adorable you learned how to read the spec, but I don’t trust you. You have an abnormally long beard, and consistently talk about waffles during meetings. If you can’t show me some facts, I’m not only going to stop reading, but I’ll probably make sarcastic references to your post when ever I’m reviewing someone’s pull request and they try to act smarter than they really are. You will become the `leftpad` of being technically correct.

Don’t worry, left-pad was the only bad one

Fair point, let’s get to it.

The section in the spec that deals with Object clearly doesn’t say anything about object order type, but just because it doesn’t say it doesn’t mean it’s not there. Since we are programmers, lets inspect the specification and do a stack trace. Object isn’t specified to have an order, but who cares. I’m not super concerned with how properties are stored internally, I just care how they come back when I ask for them. So what are some ways we get them back? Obj.keys(), for-in, etc. Let’s pick for-in for no other reason than Swift dropped support for doing plain for iteration (curse you Lattner). So skimming through the for-in head evaluation section 13.7.5.12 (such a nail-biter), you see that it doesn’t have a method specified to dictate order to an object, but internally it’s required to use obj.[[Enumerate]]() in spec 13.7.5.12. What’s helpful there, is because of my background in Objective-c, I understand what they are saying since it uses square brackets (that was a bad joke, the best kind). That or it gives me another place to look.

With the new Macbook touch bar in Xcode, you can touch and slide for as many square brackets as your heart desires…

Going down to the [[Enumerate]]() spec 9.1.11, you’ll notice this also lacks any sort of semblance of order prescribed to the object, but what it does have is another clue. In specifying the internal consistency an implementation must have to the internal [[Enumerate]] method, it specifies that property key retrieval must conform to [[OwnPropertyKeys]](). Abandoning all notion I have of a social life, or hobbies that can hold my attention longer than a YouTube video, I dug a bit deeper.

I know what you’re thinking, this is a big joke to see if Joe can trick us into reading a spec sheet. It’s true, your product manager paid me to teach you how to read the spec they give you (hahaha, no one does that). Anyways, [[OwnPropertyKeys]]() spec 9.1.12 is our landing place. Plain as day it details how the order works when an object’s properties are retrieved. First it’s going to go through and give you all of the integer indexes in ascending order (yay counting!), then it’s going to go ahead and give you properties with a string key next. This parts a bit unintuitive: it returns them in the order they were instantiated. So an object like var foo = {I: 0, 3:0, declare: 0, 1:0, a:0, thumb:0, 2:0, 4:0, war:0}; would actually come back as “1, 2, 3, 4, I, declare, a, thumb, war” instead of being alphabetically ordered. Go ahead, try it in your console, I’ll wait.

I hear thumb wars are coming out on the Nintendo Virtual Console

Now, when I started, I promised to explain why, even though ECMAScript 5 had no spec or conformity standards for object order, it still had one. The truth is I lied. People are going to lie to your whole life, better you get used to it now when you’re young. Closest I can figure is it had to do with Environment Records and how lexical addressing is typically dealt with. But at that point I ran out of Hot Pockets and gave up.

--

--