3

I am trying to understand what's the thing with javascript Objects while using them as an associative array.

From ECMA:

4.3.3 An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method.

Using them in browser (chrome):

x = { 2: 'a', 3: 'b', 1: 'c' }
> Object {1: "c", 2: "a", 3: "b"}

y = { 'b': 2, 'c': 3, 'a': 1 }
> Object {b: 2, c: 3, a: 1}

While in the first example with the numbers as keys, they became ordered, in the second example with strings, they won't ( ordered = a,b,c ).

I am using these objects with string keys and I really don't want them to change order in some stage of app(if that's even possible) because it may crash the pipeline I am using.

Question is, is this approach safe and normal for every javascript machine, or should I use other method to guarantee that order won't ever change?

Thank you!

Edit: I am using this with node.js which runs on V8 (chrome engine), which 'orders non-numerical properties in insertion order'(Felix Kling). May this behaviour of V8 change?

7
  • 7
    Ordering of properties is undefined. That means that a JavaScript runtime is free to return the properties in any order it wants, and it doesn't even have to be the same order if you ask twice. You simply cannot rely on the ordering. If you need some fixed ordering put the property names in an array. Commented Jan 12, 2015 at 16:50
  • 2
    "should I use other method to guarantee that order won't ever change?" Yes. Commented Jan 12, 2015 at 16:50
  • "It is an unordered collection" You can't rely on any order of object properties, the order can be whatever JS happens to give you. Commented Jan 12, 2015 at 16:50
  • It is an unordered collection - This statement doesn't mean that the Javascript run-time is required preserve the order in which the properties were defined. It just means that you cannot rely on the ordering of properties to frame your logic! Commented Jan 12, 2015 at 16:53
  • 1
    Here is how Chrome is currently ordering the properties: Numerical properties come first in ascending order, then non-numerical properties in insertion order. This can change any time. Commented Jan 12, 2015 at 16:54

4 Answers 4

6

Although Chrome may guarantee property order when using numbers as indexes in objects, the ECMA specification does not say it should do that, so by guarantee I'd not rely on this behavior. I suggest you to restructure your data to use arrays when you want to keep data order.

Sign up to request clarification or add additional context in comments.

Comments

1

At the end of the day, it's because V8 uses if/else everywhere in the code to determine if it's an array index or an object property and not two separate classes to handle Array and Object separately like other JS engines:

https://lastzero.net/2009/09/object-property-ordering-in-google-chrome/

Yes, Google sticks to the specs, but it also makes it difficult to pass existing data structures from other programming languages to JS, because the ordering changes unexpectedly (even John Resig was surprised!). So you have to use different (possibly slower) data structures or use a converter, which makes code more complex.

Comments

1

It depends on the environment the code is running in, and the methods being used to iterate over the keys.

In ES5 and earlier, there is no defined order, regardless of the method used.

In ES6+, some methods which iterate over keys (but not all) are guaranteed to iterate in order over:

(1) increasing numeric keys (eg, 0, 1, 2), followed by

(2) non-numeric keys in insertion order, followed by

(3) symbols in insertion order.

The methods which are guaranteed to behave this way are, among others:

These all invoke the internal method [[OwnPropertyKeys]], which guarantees the order.

Methods which are not guaranteed to iterate in any order, even in ES6+ environments, include:

  • for..in
  • Object.keys, Object.values, Object.entries
  • JSON.stringify

These methods all call EnumerateObjectProperties, which explicitly states:

The mechanics and order of enumerating the properties is not specified

All that said, even though order isn't guaranteed, in newer environments, the above methods will almost always iterate in the same deterministic order as Reflect.ownKeys anyway. Maybe you shouldn't depend on it, but it'll probably work, at least for now.

If you want a

method to guarantee that order won't ever change?

then to dependably iterate over an object, you should iterate using Reflect.ownKeys or Object.getOwnPropertyNames.

May this behaviour of V8 change?

If you use one of the methods guaranteed to iterate in a particular order, the behavior will not change, because Javascript pretty much always retains backwards compatibility, and now that an required order has been described in the specification, no future changes will change that order.

Comments

0

I read from the spec.: Arrays are ordered, Objects not. Chrome seems to make no difference between number and string of numbers. (for performance reason?) I sometimes sidestep to an additional array of keys where needed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.