如何按编写顺序迭代 javascript 对象属性

IT技术 javascript
2021-03-01 14:04:08

我在我的代码中发现了一个错误,我希望通过最少的重构工作来解决它。此错误发生在 Chrome 和 Opera 浏览器中。问题:

var obj = {23:"AA",12:"BB"};
//iterating through obj's properties
for(i in obj)
  document.write("Key: "+i +" "+"Value: "+obj[i]);

FF,IE 输出 键:23 值:AA 键:12 值:BB

Opera 和 Chrome 中的输出(错误)
键:12 值 BB
键:23 值 AA

我试图制作一个像这样的逆序对象

var obj1={"AA":23,"BB":12};
for(i in obj1)
  document.write("Key: "+obj[i] +" "+"Value: "+i);

但是输出是一样的。有没有办法让所有浏览器通过小的更改获得相同的行为?

4个回答

不可以。JavaScript 对象属性没有固有的顺序。for...in循环运行的顺序完全靠运气

如果您想要订购,则必须改用数组:

var map= [[23, 'AA'], [12, 'BB']];
for (var i= 0; i<map.length; i++)
    document.write('Key '+map[i][0]+', value: '+map[i][1]);
好吧,当程序员在没有深入了解他正在写的内容的情况下进行编写时,就会发生这种情况:)。
2021-04-27 14:04:08
详细地说,这是因为 Javascript 对象是哈希(想想哈希表)。如果要排序,请使用数组。
2021-05-19 14:04:08
讨厌的程序员!我恨他们!:-)
2021-05-19 14:04:08

我认为您会发现唯一可靠的方法是使用数组而不是关联数组,例如:

var arr = [{key:23,val:"AA"},{key:12,val:"BB"}];
for(var i=0; i<arr.length; i++)
  document.write("Key: "+arr[i].key +" "+"Value: "+arr[i].val);
JavaScript 具有带有属性的对象,而不是关联数组。如果它们是数组,它们将被排序。
2021-04-20 14:04:08
同意 - 但是具有属性的对象通常(我承认并不完全正确)称为“关联数组”,或者至少用于该目的。“关联数组”(更一般地说,不是 javascript 意义上的)通常不被认为等同于有序值 - 它们被认为是名称/值对的集合。
2021-04-21 14:04:08

@bobince 是对的,对象不保留任何排序元数据。

在我的情况下,重构为数组没有意义,所以我提交了另一个解决方案:根据您的顺序创建一个数组并使用它按顺序映射您的对象属性:

const obj = {
    'r': '#f00',
    'g': '#0f0',
    'b': '#00f',
};
const objMap = ['b','r','g'];

objMap.map((key, index) => {
    console.log(`array index: ${index}`);
    console.log(`object index: ${key}`);
    console.log(`object property: ${obj[key]}\n`);
});

输出:

array index: 0
object index: b
object property: #00f

array index: 1
object index: r
object property: #f00

array index: 2
object index: g
object property: #0f0

当对象属性标识符是字母字符串时,我没有得到您的结果。IE8、FF5、Chrome 12、Opera 9.8 都保持了创建顺序,即

键:AA 值:23 键:BB 值:12

当标识符是数字时,结果与您的匹配:-

IE8, FF5 --> 键:23 值:AA 键:12 值:BB

Opera、Chrome --> 键:12 值:BB 键:23 值:AA

Opera 和 Chrome 的存储顺序与创建顺序相反,因为 12 小于 23,因此如果您使用它,请说:-

var obj = {2:"AA",12:"BB"};

然后你会在所有 4 个浏览器中得到这个结果:-

键:2 值:AA 键:12 值:BB

因此,使用数字作为标识符会导致差异。如果标识符是字母顺序,那么 4 个浏览器的创建和存储属性顺序是相同的。尽管 ECMA 规定存储的顺序不需要与创建顺序相关。

如果字符串标识符是数字,例如“23”和“12”,那么 Opera 和 Chrome 会将它们视为数字并再次颠倒创建顺序,因此也不允许使用该类型。'23a' 类型和 'a23' 类型都可以。

要回答您的问题,请使用非数字字符串标识符,并且行为将在 4 个浏览器(以及可能所有浏览器)中相同。

ECMAScript 规范声明顺序未定义,这并不意味着它不应该是有序的。这意味着如果浏览器决定更改底层数据结构并且碰巧以不同的顺序将密钥返回给您,那么规范完全可以。这就是为什么你不应该依赖它,即使它现在运行良好。您还必须记住,实现可以从一个平台更改为另一个平台,也可以在浏览器的每个版本中更改。
2021-04-26 14:04:08