我可以遍历 JavaScript 对象并倒序吗?

48

我有一个像这样的JavaScript对象:

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

我可以像这样循环:

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

将按照 one > two > three 的顺序循环遍历属性。

但有时我需要逆序进行,所以我想执行相同的循环,但是 three > two > one

问题:
是否有"object-reverse"函数。如果它是一个数组,我可以使用unshift进行反转或构建一个新数组,但是在我需要反向循环它的属性时,我不知道该怎么办。 有任何想法吗?

谢谢!


2
我不会依赖于对象键的任何顺序。如果需要,可以使用 Object.keys() 提取键,对它们进行排序,然后按排序后的顺序访问属性。 - Sirko
嗯,好主意。让我们试试看。 - frequent
还可以阅读以下内容:这个这个 - Lionel Chan
5个回答

40

Javascript对象没有固定的内在顺序,因此不存在“逆序”顺序。

4.3.3 对象(Object) 是 Object 类型的成员。它是一个无序集合,每个属性都包含了一个原始值(primitive value)、对象或函数。存储在对象属性中的函数称为方法(method)。

浏览器似乎会按照添加到对象中的顺序返回属性,但由于这不是标准行为,您可能不应该依赖这种行为。

一个简单的函数可以按照与浏览器的 for..in 相反的顺序调用每个属性的函数,如下所示:

// 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]); });

工作中的JsBin: http://jsbin.com/aPoBAbE/1/edit

我再次强调,for..in语句的顺序不是保证的,因此反向顺序也不是保证的。请谨慎使用!


1
我最终使用了数组而不是对象,因为它更容易排序和反转。无论如何还是谢谢。 - frequent
明智的选择。你的使用场景听起来更适合使用数组。 - Tibos
喜欢这个解决方案。我不得不使用一个对象,所以谢谢你,你应该得到更多的赞。 - PaoloCargnin
1
顺序似乎与输入的顺序相同,但如果您的键是数字,则它们似乎会按升序循环。这是我能找到的唯一一种可能导致顺序与添加属性到对象的方式不同的情况。因此,循环遍历“var obj = {2:“two”,1:“one”,3:“three”}”将显示“onetwothree”,而不是“twoonethree”。只是一个观察! - Mike

27

为什么没有人提到 Object.keys()

你可以使用 Object.keys() 来获取一个对象属性的数组,以它原本的顺序排序,然后你可以使用数组方法来反转或过滤需要的内容。

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


这也是我的猜测。我只是困惑为什么这个答案的赞数如此之少。 这个解决方案有什么可能出错的地方吗?(尽管顺序不能保证) - Timo Giese
真的很喜欢这个答案。 - Oak

6

无法通过对象反向循环,但如果您以相反的顺序重新创建对象,则可以解决问题!然而,请注意,没有任何东西能保证对象的顺序在更改后仍然相同,因此可能会导致一些有趣的结果,但大多数情况下它是有效的...

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;
}

只需像这样在您的对象上执行交换-
MyObject = ReverseObject(MyObject);

循环将如下所示-
for (var KeysAreNowBackwards in MyObject){
    alert(MyObject[KeysAreNowBackwards]);
} 

3
我想提出一些修改建议: 第3行 var NewObj = {},这样我们就可以返回对象而不是数组, 第8行 NewObj[TempArr[i]] = Obj[TempArr[i]];,因为你的代码返回了一个空数组。 - user4547691

5

这个答案与其他一些答案类似,但是一些用户可能会发现下面的代码更容易复制粘贴到自己的应用程序中:

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

针对问题描述中的对象"foo",这段代码会按相反的顺序输出对象的元素:"else","thing","some"。


0

您可以使用

Object.keys

需要注意的一点是,如果键是数字,它会返回一个已排序的键列表。您可能需要相应地进行更改。

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)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接