Orpheus
Orpheus

Reputation: 767

Chrome array ordering not correct vs other browsers

Originally I had this issue a while back where while the dataset was correct, relying on ordering in javascript as far as an array is concerned wasn't correct, so my solution was something like this, insofar as the json being returned

var json = { //Returned from a database
  data: {
    _0: {key1: val1, key2: val2},
    _1: {key1: val1, key2: val2},
    ...etc etc etc

  }
};

var new_arr = [];
for(var i = 0; i < Object.keys(json.data).length; i++) {
  var obj = json.data["_"+i];
  new_arr.push(obj);
}
console.log(new_arr);

In IE8-11, Firefox, Opera (or any other browser) this behaves as you'd expect. The order is preserved per the keys in the original json object returned.

Chrome, however, puts this out of order abritrarily. The array is not in the expected order. For example, in at least one case, "_36" appears before "_0" in the console.log, then another key is arbitrarily out of order.

Keep in mind the JSON object returns correctly. It's just reordering the data element of the object isn't being pushed into an array correctly. What am I missing?

Note 1: The key/value pairings inside of _0 et al. do not matter. That is not where the issue is. It is with me running a loop, and the array not being in the right order.

Note 2: The loop is correct. It's accessing the properties of json.data in the right order. The problem is that they aren't going into the array in the right order.

Upvotes: 1

Views: 402

Answers (1)

Pablo Lozano
Pablo Lozano

Reputation: 10342

There is no order between the elements of a javascript object, so if you have something like

var data: {
  _0: 'zero',
  _1: 'one'   
}

There is no "first attribute" and "second attribute", so you cannot expect that the array of keys returned by Object.keys follows any kind of order. The only restriction is that

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

Extracted from the MDN page (bold are mine).

If an implementation defines a specific order of enumeration for the for-in statement, the same order must be used for the elements of the array returned [by Object.keys]

from the ECMA specs.

If you need to ensure the order, sort the array of keys before looping:

var new_arr = [];
var keys=Object.keys(json.data);
keys.sort(function () {....}); //custom comparator here
for(var i = 0; i < keys.length; i++) {
  var obj = json.data["_"+i];
  new_arr.push(obj);
}

Upvotes: 3

Related Questions