开发者

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

开发者 https://www.devze.com 2022-12-27 14:10 出处:网络
I identified a bug in my code which I hope to solve with minimal refactoring effort. This bug occurs in Chrome and Opera browsers.

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:"AA",12:"BB"};
//iterating through obj's properties
for(i in obj)
  document.write("Key: "+i +" "+"Value: "+obj[i]);

Output in FF,IE Key: 23 Value: AA Key: 12 Value: BB

Output in Opera and Chrome (Wrong)

K开发者_StackOverflow中文版ey: 12 Value BB

Key: 23 Value AA

I attempted to make an inverse ordered object like this

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

However the output is the same. Is there a way to get for all browser the same behaviour with small changes?


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


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


@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


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

精彩评论

暂无评论...
验证码 换一张
取 消