48

So I have a JavaScript object like this:

foo = {
  "one": "some",
  "two": "thing",
  "three": "else"
};

I can loop this like:

for (var i in foo) {
  if (foo.hasOwnProperty(i)) {
    // do something
  }
}

Which will loop through the properties in the order of one > two > three.

However sometimes I need to go through in reverse order, so I would like to do the same loop, but three > two > one.

Question:
Is there an "object-reverse" function. If it was an Array, I could reverse or build a new array with unshift but I'm lost with what to do with an object, when I need to reverse-loop it's properties. Any ideas?

Thanks!

frequent
  • 27,643
  • 59
  • 181
  • 333
  • 2
    I would not rely on any order concerning object keys. If that is needed, extract the key using `Object.keys()`, sort them and then access the properties in the sorted order. – Sirko Sep 24 '13 at 09:37
  • hm. good idea. let's try – frequent Sep 24 '13 at 09:39
  • Also read this: [this](http://stackoverflow.com/questions/12388412/js-object-key-sequence) and [this](http://stackoverflow.com/questions/280713/elements-order-in-a-for-in-loop) – Lionel Chan Sep 24 '13 at 09:42

5 Answers5

40

Javascript objects don't have a guaranteed inherent order, so there doesn't exist a "reverse" order.

4.3.3 Object 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.

Browsers do seem to return the properties in the same order they were added to the object, but since this is not standard, you probably shouldn't rely on this behavior.

A simple function that calls a function for each property in reverse order as that given by the browser's for..in, is this:

// f is a function that has the obj as 'this' and the property name as first parameter
function reverseForIn(obj, f) {
  var arr = [];
  for (var key in obj) {
    // add hasOwnPropertyCheck if needed
    arr.push(key);
  }
  for (var i=arr.length-1; i>=0; i--) {
    f.call(obj, arr[i]);
  }
}

//usage
reverseForIn(obj, function(key){ console.log('KEY:', key, 'VALUE:', this[key]); });

Working JsBin: http://jsbin.com/aPoBAbE/1/edit

Again i say that the order of for..in is not guaranteed, so the reverse order is not guaranteed. Use with caution!

Jake N
  • 10,535
  • 11
  • 66
  • 112
Tibos
  • 27,507
  • 4
  • 50
  • 64
  • 1
    I ended up using an array instead of an object, because it's just easier to sort and reverse. Thanks anyway – frequent Sep 24 '13 at 14:58
  • Wise choice. Your use case sounds like an array is a better fit. – Tibos Sep 24 '13 at 15:17
  • Love this solution. I had to use an object so... thanks man, you deserve more upvotes. – PaoloCargnin Jun 18 '17 at 18:17
  • 1
    The order does seem to be as entered however, if your keys are numbers they seem to loop through in ascending order. This is the only case I can find in which the order may be different to the way you add properties to the object. So looping through 'var obj = {2: "two", 1: "one", 3: "three"}' would display 'onetwothree', not 'twoonethree'. Just an observation! – Mike Jul 11 '19 at 15:29
27

Why there is no one has mentioned Object.keys() ?

you can get Array of Object's properties ordered as it is, then you can reverse it or filter it as you want with Array methods .

let foo = {
  "one": "some",
  "two": "thing",
  "three": "else"
};

// Get REVERSED Array of Propirties
let properties = Object.keys(foo).reverse();
// "three"
// "two"
// "one"

// Then you could use .forEach / .map
properties.forEach(prop => console.log(`PropertyName: ${prop}, its Value: ${foo[prop]}`));

// PropertyName: three, its Value: else
// PropertyName: two, its Value: thing
// PropertyName: one, its Value: some
Maged Mohamed
  • 752
  • 8
  • 7
  • This would have been also my guess. I am just confused this answer has so less upvotes. Anything that can go wrong with this solution? (Despite that the order cannot be guaranteed) – Timo Giese Jun 11 '20 at 15:29
  • Really like this answer – Oak Jan 21 '21 at 15:55
6

There is no way to loop through an object backwards, but if you recreate the object in reverse order then you are golden! Be cautions however, there is nothing that says the order of the object will stay the same as it changes and so this may lead to some interesting outcome, but for the most part it works...

function ReverseObject(Obj){
    var TempArr = [];
    var NewObj = [];
    for (var Key in Obj){
        TempArr.push(Key);
    }
    for (var i = TempArr.length-1; i >= 0; i--){
        NewObj[TempArr[i]] = [];
    }
    return NewObj;
}

The just do the swap on your object like this-

MyObject = ReverseObject(MyObject);

The loop would then look like this-

for (var KeysAreNowBackwards in MyObject){
    alert(MyObject[KeysAreNowBackwards]);
} 
ctay
  • 379
  • 4
  • 7
  • 3
    There are a couple changes that I want suggest : _line 3_ `var NewObj = {}` in this way we return object instead of array, _line 8_ `NewObj[TempArr[i]] = Obj[TempArr[i]];` because your code return empty array –  Dec 08 '15 at 17:38
5

This answer is similar to a couple of the others, but some users might find the code below easier to copy-paste for their own uses:

Object.keys(foo).reverse().forEach(function(key) { console.log(foo[key]) });

For an object "foo" as described in the question, this code will output the object elements in reverse order: "else", "thing", "some"

Lorien Brune
  • 830
  • 10
  • 16
0

You can use

Object.keys

One thing to take care of is that it returns a sorted list of keys (if the keys are numerical). You might need to change it accordingly.

a =   {'d':'stack','l':'overflow','b':'out','a':'first','z':'empty'}
out = Object.keys(a).reverse()
console.warn("When key contains characters : "+out)

a =   {'1':'stack','4':'overflow','2':'out','5':'first','3':'empty'}
out = Object.keys(a).reverse()
console.warn("When key is a numerical string : "+out)
shekhar chander
  • 600
  • 8
  • 14