Is there a way to sort/order keys in JavaScript objects?

Solution 1:

Not within the object itself: the property collection of an object is unordered.

One thing you could do is use Object.keys(), and sort the Array, then iterate it.

Object.keys(data)
      .sort()
      .forEach(function(v, i) {
          console.log(v, data[v]);
       });

Patches (implementations) for browsers that do not support ECMAScript 5th edition:

  • Object.keys

  • Array.forEach

Solution 2:

here's a nice functional solution:

basically,

  1. extract the keys into a list with Object.keys
  2. sort the keys
  3. reduce list back down to an object to get desired result

ES5 Solution:

not_sorted = {b: false, a: true};

sorted = Object.keys(not_sorted)
    .sort()
    .reduce(function (acc, key) { 
        acc[key] = not_sorted[key];
        return acc;
    }, {});

console.log(sorted) //{a: true, b: false}

ES6 Solution:

not_sorted = {b: false, a: true}

sorted = Object.keys(not_sorted)
    .sort()
    .reduce((acc, key) => ({
        ...acc, [key]: not_sorted[key]
    }), {})

console.log(sorted) //{a: true, b: false}

Solution 3:

Yes, there is. Not within ECMAScript standard, but supported across browsers and Node.js, and apparently stable. See https://stackoverflow.com/a/23202095/645715.

EDIT: This returns an object in which the keys are ordered. You can use Object.keys(...) to get the ordered keys from the object.

Why worry about object key order? The difference can matter in some applications, such as parsing XML with xml2js which represents XML as nested objects, and uses XML tags as hash keys.

There are a couple notes:

  • keys that look like integers appear first and in numeric order.
  • keys that look like strings appear next and in insertion order.
  • this order is reported by Object.keys(obj)
  • the order as reported by for (var key in obj) {...} may differ in Safari, Firefox

The function returns an object with sorted keys inserted in alphabetic order:

function orderKeys(obj, expected) {

  var keys = Object.keys(obj).sort(function keyOrder(k1, k2) {
      if (k1 < k2) return -1;
      else if (k1 > k2) return +1;
      else return 0;
  });

  var i, after = {};
  for (i = 0; i < keys.length; i++) {
    after[keys[i]] = obj[keys[i]];
    delete obj[keys[i]];
  }

  for (i = 0; i < keys.length; i++) {
    obj[keys[i]] = after[keys[i]];
  }
  return obj;
}

Here's a quick test:

var example = { 
      "3": "charlie",
      "p:style": "c",
      "berries": "e",
      "p:nvSpPr": "a",
      "p:txBody": "d",
      "apples": "e",
      "5": "eagle",
      "p:spPr": "b"
    }

var obj = orderKeys(example);

this returns

{ '3': 'charlie',
  '5': 'eagle',
  apples: 'e',
  berries: 'e',
  'p:nvSpPr': 'a',
  'p:spPr': 'b',
  'p:style': 'c',
  'p:txBody': 'd' }

You can then get the ordered keys as:

Object.keys(obj) 

Which returns

["3", "5", "apples", "berries", "p:nvSpPr", "p:spPr", "p:style", "p:txBody"]