How to iterate javascript object properties in the order they were written

前端 未结 4 1629
抹茶落季
抹茶落季 2020-11-29 12:00

I identified a bug in my code which I hope to solve with minimal refactoring effort. This bug occurs in Chrome and Opera browsers. Problem:

var obj = {23:\"A         


        
相关标签:
4条回答
  • 2020-11-29 12:34

    I think you'll find the only reliable way to do this would be to use an array rather than an associative array, eg:

    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);
    
    0 讨论(0)
  • 2020-11-29 12:35

    I did not get your result when the object property identifiers were alphabetic strings. IE8, FF5, Chrome 12, and Opera 9.8 all kept the creation order, i.e.

    Key: AA Value: 23 Key: BB Value: 12

    It was when the identifiers were numbers that the results matched yours:-

    IE8, FF5 --> Key: 23 Value: AA Key: 12 Value: BB

    Opera, Chrome --> Key: 12 Value: BB Key: 23 Value: AA

    Opera and Chrome are storing in reverse of creation order because 12 is less than 23, so if you use instead say:-

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

    then you get this result for all 4 browsers:-

    Key: 2 Value: AA Key: 12 Value: BB

    So it is the use of numbers as identifiers that causes the discrepancy. If identifiers are alphabetic then both creation and stored property orders are the same for the 4 browsers. This is despite ECMA rules that the stored order need not be related to creation order.

    If the string identifiers are numeric e.g. '23' and '12', then Opera and Chrome treat them as numbers and again reverse the creation order, so that type are not permitted either. '23a' types are OK as are 'a23' type.

    To answer your question, use non-numeric string identifiers and the behaviour will be the same across the 4 browsers (and possibly all browsers).

    0 讨论(0)
  • 2020-11-29 12:41

    No. JavaScript Object properties have no inherent order. It is total luck what order a for...in loop operates.

    If you want order you'll have to use an array instead:

    var map= [[23, 'AA'], [12, 'BB']];
    for (var i= 0; i<map.length; i++)
        document.write('Key '+map[i][0]+', value: '+map[i][1]);
    
    0 讨论(0)
  • 2020-11-29 12:46

    @bobince is right, Objects don't keep any ordering metadata.

    In my case it didn't make sense to refactor to an array, so I submit another solution: create an array with your ordering and use it to map your object properties in order:

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

    Output:

    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
    
    0 讨论(0)
提交回复
热议问题