代码之家  ›  专栏  ›  技术社区  ›  Eugeniu Torica

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

  •  14
  • Eugeniu Torica  · 技术社区  · 16 年前

    我在代码中发现了一个bug,我希望用最少的重构工作来解决它。这个错误出现在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输出 密钥: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 回复  |  直到 7 年前
        1
  •  20
  •   bobince    16 年前

    不。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]);
    
        2
  •  2
  •   Graza    16 年前

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

    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);
    
        3
  •  0
  •   Gerbus    7 年前

    @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
    
        4
  •  -2
  •   John    15 年前

    当对象属性标识符是字母字符串时,我没有得到您的结果。IE8、FF5、Chrome12和Opera9.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"};
    

    然后您将得到这四个浏览器的结果:

    键:2值:aa键:12值:bb

    因此,正是数字作为标识符的使用导致了这种差异。如果标识符是按字母顺序排列的,那么对于4个浏览器,创建和存储的属性顺序都是相同的。尽管ecma规则规定存储顺序不必与创建顺序相关,但这一点仍然存在。

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

    要回答您的问题,请使用非数字字符串标识符,4个浏览器(可能是所有浏览器)的行为都是相同的。