28
var addObjectResponse = [{
    'DateTimeTaken': '/Date(1301494335000-0400)/',
    'Weight': 100909.090909091,
    'Height': 182.88,
    'SPO2': '222.00000',
    'BloodPressureSystolic': 120,
    'BloodPressureDiastolic': 80,
    'BloodPressurePosition': 'Standing',
    'VitalSite': 'Popliteal',
    'Laterality': 'Right',
    'CuffSize': 'XL',
    'HeartRate': 111,
    'HeartRateRegularity': 'Regular',
    'Resprate': 111,    
    'Temperature': 36.6666666666667,
    'TemperatureMethod': 'Oral',    
    'HeadCircumference': '',    
}];

This is a sample object which i am getting from back end, now i want to change the order of the object. I don't want to sort by name or size... i just want to manually change the order...

John Cooper
  • 7,343
  • 31
  • 80
  • 100
  • 3
    You want to change the order of the key/value pairs? Why? – alnorth29 Aug 05 '11 at 16:54
  • 1
    possible duplicate of [Elements order - for (... in ...) loop in javascript](http://stackoverflow.com/questions/280713/elements-order-for-in-loop-in-javascript) – KARASZI István Aug 05 '11 at 16:59
  • Just write them out in the order you want. You can create an array of keys in the order you want and access the object using that array – mplungjan Aug 05 '11 at 17:03

14 Answers14

39

If you create a new object from the first object (as the current accepted answer suggests) you will always need to know all of the properties in your object (a maintenance nightmare).

Use Object.assign() instead.

*This works in modern browsers -- not in IE or Edge <12.

const addObjectResponse = {
  'DateTimeTaken': '/Date(1301494335000-0400)/',
  'Weight': 100909.090909091,
  'Height': 182.88,
  'SPO2': '222.00000',
  'BloodPressureSystolic': 120,
  'BloodPressureDiastolic': 80,
  'BloodPressurePosition': 'Standing',
  'VitalSite': 'Popliteal',
  'Laterality': 'Right',
  'CuffSize': 'XL',
  'HeartRate': 111,                              // <-----
  'HeartRateRegularity': 'Regular',              // <-----
  'Resprate': 111,    
  'Temperature': 36.6666666666667,
  'TemperatureMethod': 'Oral',    
  'HeadCircumference': '',    
};

// Create an object which will serve as the order template
const objectOrder = {
  'HeartRate': null,
  'HeartRateRegularity': null,
}
  
const addObjectResource = Object.assign(objectOrder, addObjectResponse);

The two items you wanted to be ordered are in order, and the remaining properties are below them.

Now your object will look like this:

{           
  'HeartRate': 111,                              // <-----
  'HeartRateRegularity': 'Regular',              // <-----
  'DateTimeTaken': '/Date(1301494335000-0400)/',
  'Weight': 100909.090909091,
  'Height': 182.88,
  'SPO2': '222.00000',
  'BloodPressureSystolic': 120,
  'BloodPressureDiastolic': 80,
  'BloodPressurePosition': 'Standing',
  'VitalSite': 'Popliteal',
  'Laterality': 'Right',
  'CuffSize': 'XL',
  'Resprate': 111,    
  'Temperature': 36.6666666666667,
  'TemperatureMethod': 'Oral',    
  'HeadCircumference': '',    
}
Jeff Vdovjak
  • 1,833
  • 16
  • 21
  • This works great for me, except, when a key is zero (the number zero). It will ALWAYS come first, no matter what. – hitchhiker Mar 26 '22 at 13:51
  • Do you mean `const addObjectResource = Object.assign(objectOrder, addObjectResponse);`? Confusing name conventions lead to spelling errors! – Joe Moore Jan 12 '23 at 14:57
22

I wrote this small algorithm which allows to move keys, it's like jQuery .insertAfter() method. You have to provide:

//currentKey: the key you want to move
//afterKey: position to move-after the currentKey, null or '' if it must be in position [0]
//obj: object


function moveObjectElement(currentKey, afterKey, obj) {
    var result = {};
    var val = obj[currentKey];
    delete obj[currentKey];
    var next = -1;
    var i = 0;
    if(typeof afterKey == 'undefined' || afterKey == null) afterKey = '';
    $.each(obj, function(k, v) {
        if((afterKey == '' && i == 0) || next == 1) {
            result[currentKey] = val; 
            next = 0;
        }
        if(k == afterKey) { next = 1; }
        result[k] = v;
        ++i;
    });
    if(next == 1) {
        result[currentKey] = val; 
    }
    if(next !== -1) return result; else return obj;
}

Example:

var el = {a: 1, b: 3, c:8, d:2 }
el = moveObjectElement('d', '', el); // {d,a,b,c}
el = moveObjectElement('b', 'd', el); // {d,b,a,c}
Ben K.
  • 449
  • 4
  • 7
12

I like the approved answer by Chamika Sandamal. Here's a simple function that uses their same logic with a little be of freedom to change the order as you need it.

function preferredOrder(obj, order) {
    var newObject = {};
    for(var i = 0; i < order.length; i++) {
        if(obj.hasOwnProperty(order[i])) {
            newObject[order[i]] = obj[order[i]];
        }
    }
    return newObject;
}

You give it an object, and an array of the key names you want, and returns a new object of those properties arranged in that order.

var data = {
    c: 50,
    a: 25,
    d: 10,
    b: 30
};

data = preferredOrder(data, [
    "a",
    "b",
    "c",
    "d"
]);

console.log(data);

/*
    data = {
        a: 25,
        b: 30,
        c: 50,
        d: 10
    }
*/

I'm copying and pasting from a big JSON object into a CMS and a little bit of re-organizing of the source JSON into the same order as the fields in the CMS has saved my sanity.

Motionharvest
  • 407
  • 4
  • 10
12

You can't order JavaScript object key/value pairs. It's stored in its own internal format, so you should never rely on the order of that. In JS, everything is an Object, even an Array. So sometimes you can introduce bugs when using array notation and object notation together (for x in var)

jontsai
  • 682
  • 1
  • 6
  • 13
  • 3
    while this is true, this doesn't resemble real-world usage where templates are often rendered by looping over object properties. And when you loop over them, they have an order. Altering this order is... fragile, but IMO it should be added. – ProblemsOfSumit Dec 20 '16 at 15:52
  • 3
    I was also under same impression until I have seen this MDN page: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map The first line says **The Map object holds key-value pairs and remembers the original insertion order of the keys** – polavishnu Apr 25 '19 at 16:50
  • 2
    This answer was correct at the time but is now outdated and incorrect: You can absolutly depend on the order of object keys starting with ECMAScript 6. It has become part of the JavaScript specification. See answer from @Tim Down or this link: https://2ality.com/2015/10/property-traversal-order-es6.html – EliteRaceElephant Aug 07 '21 at 09:52
  • It's possible to order the attributes of an object now a days. – Mateen Oct 18 '21 at 05:18
11

2020 Update

The answer below was correct at time of writing in 2011. However, since ES6, enumeration order has been specified as part of the language. Here's a nice article summarising this: https://2ality.com/2015/10/property-traversal-order-es6.html

Original answer

Properties of an object in JavaScript do not have an order. There may appear to be an order in some browsers but the ECMAScript specification defines object property enumeration order as being implementation-specific so you should not assume one browser's behaviour will be the same as another's. Chrome, for example, does not use the same ordering as some other browsers: see this lengthy bug report for at least as much discussion of this issue as you could possibly want.

If you need a specific order, use an array, or two arrays (one for keys and one for values).

Tim Down
  • 318,141
  • 75
  • 454
  • 536
7

You can use Object.keys():

var obj = {
    a: 1,
    b: 2,
    c: 4
};

var new_obj = {};

Object.keys(obj)
.sort(function(a, b) {
    /** Insert your custom sorting function here */
    return a - b;
})
.forEach(function(key) {
    new_obj[key] = obj[key];
});

obj = new_obj;
vardump
  • 658
  • 1
  • 10
  • 17
5

if you want to manually reorder. simply create new object and assign values using old object.

var newObject= [{
    'DateTimeTaken': addObjectResponse.DateTimeTaken,
    'Weight': addObjectResponse.Weight,
    'Height': addObjectResponse.Height,
    'SPO2': addObjectResponse.SPO2 
}];
Chamika Sandamal
  • 23,565
  • 5
  • 63
  • 86
  • 25
    That has no more order than the original object. Object properties do not have a consistent enumeration order in JavaScript. – Tim Down Aug 06 '11 at 15:29
  • 5
    There may be a use case where this is necessary, such as rendering an object with a templating library – amigolargo Jun 13 '16 at 11:09
  • 4
    Object properties *do* have a consistent order in javascript, which is the order in which they are added. see `Object.prototype.entries(someObject);` – Jay Day Zee Apr 23 '18 at 12:58
  • 2
    @JayDayZee [I did look it up](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries). “The order of the array returned by Object.entries() does not depend on how an object is defined.” – Tadhg McDonald-Jensen Feb 20 '19 at 23:56
  • There is an ordering, but that ordering is not necessarily the ordering used by `Object.entries`. The order is integer keys, in ascending order, then string keys, in the order they were added, then symbol keys, in the order they were added. (https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys). – Paul Brannan Feb 21 '20 at 19:39
  • This is a maintenance nightmare! What if you are expecting a new property? You would have to edit your code. You should use Object.assign() with this technique. (See my answer below) – Jeff Vdovjak Feb 27 '20 at 22:25
3

If you do not want to create a new object, you can use the following code snippet.

function orderKey(obj, keyOrder) {
    keyOrder.forEach((k) => {
        const v = obj[k]
        delete obj[k]
        obj[k] = v
    })
}

here is a codepen: https://codepen.io/zhangyanwei/pen/QJeRxB

张焱伟
  • 61
  • 7
  • This is an elegant solution, *especially* because it won't lose key:value pairs if the data being sent changes. However, you still need to **know all of the keys**. Any keys not identified in keyOrder will be at the front of the object. – Jeff Vdovjak Feb 27 '20 at 21:09
  • using `Object.assign()` will allow unknown key:pairs to be placed at the bottom. – Jeff Vdovjak Feb 27 '20 at 23:37
  • 1
    Also, sadly, this won't work for numeric keys – Berci Apr 09 '21 at 18:53
  • This method is a little tricky. You should use a sorted array for keys rather than update the object. - that would be the safest approach. – 张焱伟 Apr 15 '21 at 07:30
1

I think that's not possible in JavaScript.

You can create an array which will contain the field names in your order and you can iterate through this array and fetch the fields from the actual object.

KARASZI István
  • 30,900
  • 8
  • 101
  • 128
0

Just refer to the object keys in the order that you like:

aKeys = [
  addObjectResponse[0].DateTimeTaken,
  addObjectResponse[0].Weight,
  addObjectResponse[0].Height,
  ...etc...
]
silverstrike
  • 522
  • 2
  • 7
0

I wrote a quick function in TypeScript that takes 2 arguments. The first is the array of objects you want to change the keys of, the second is an array of strings that represent the order of keys you'd like returned.

type GenericObject = Record<string, any> | null;

const order:Function = (data: Array<GenericObject>, order: Array<string>): Array<GenericObject> => {
    return data.map((node) => {
        return order.reduce((runningValue, currentValue) => {
            return Object.assign(runningValue, { [currentValue]: node?.[currentValue]});
        }, {});
    });
};

And here is an example of calling it:

const data: Array<GenericObject> = [
    { b: 1, a: 2},
    { b: 3, a: 4},
];

const orderIWant: Array<string> = ['a', 'b'];

const ordered: Array<GenericObject> = order(data, orderIWant);

console.log(ordered); 
// [ { a: 2, b: 1 }, { a: 4, b: 3 } ]
Individual11
  • 374
  • 4
  • 16
0

Spread syntax seems to provide full control over property ordering. Combined with Array.prototype.map() reordering using spread will be applied to every item in your list of objects.

let addObjectResponse = [{
    'DateTimeTaken': '/Date(1301494335000-0400)/',
    'Weight': 100909.090909091,
    'Height': 182.88,
    'HeartRate': 111,
  },
  {
    'DateTimeTaken': '/Date(1301494336000-0900)/',
    'Weight': 100888.090977791,
    'Height': 174.67,
    'HeartRate': 99,
  }
];

addObjectResponse = addObjectResponse.map(item => {
  return {
    DateTimeTaken: item.DateTimeTaken,
    HeartRate: item.HeartRate + 1,
    ...item
  }
})

/*
[
  {
    DateTimeTaken: '/Date(1301494335000-0400)/',
    HeartRate: 111,
    Weight: 100909.090909091,
    Height: 182.88
  },
  {
    DateTimeTaken: '/Date(1301494336000-0900)/',
    HeartRate: 99,
    Weight: 100888.090977791,
    Height: 174.67
  }
]
*/
Will P
  • 419
  • 5
  • 8
-1
function orderKeys(obj, keys){
    const newObj = {};
    for(let key of keys){
        newObj[key] = obj[key];
    }
    return newObj;
}
ricka
  • 1,107
  • 1
  • 11
  • 13
-1

keysInOrder below is an array of ordered keys you need first. Remaining keys will be added in the existing sequence

function orderKeys(obj, keysInOrder) {
  let newObj = {};
  for (key of keysInOrder)
    if (Object.keys(obj).includes(key) && !Object.keys(newObj).includes(key))
      newObj[key] = obj[key];
  for (key of Object.keys(obj))
    if (!Object.keys(newObj).includes(key))
      newObj[key] = obj[key];
  return newObj;
}
Visv M
  • 431
  • 4
  • 13
  • See "[answer]" and [Explaining entirely code-based answers](https://meta.stackoverflow.com/q/392712/128421)". While this might be technically correct, it doesn't explain why it solves the problem or should be the selected answer. We should educate along with helping solve the problem. – the Tin Man Mar 04 '23 at 22:52