for.in的迭代顺序 - 不是通过插入(更多?)

时间:2017-03-04 11:47:01

标签: javascript sorting for-in-loop

根据我的研究,for..in循环中键的顺序应该是未定义/不可靠的 - 但是,如果不受干扰,应该按插入顺序 - 但它不是:

我从数据库中获取此数据对象,按名称排序:

var travel = {  
    '2': { name: 'bus',  price: 10 },  
    '3': { name: 'foot', price: 0 },  
    '1': { name: 'taxi', price: 100 }  
}  
for (way in travel) console.log( travel[way].name ) // => taxi, bus, foot  

按键以数字方式排序(在所有Chrome,Firefox和Edge中)。为什么呢?

并且(因为我错了)如何按.name排序?#/ p>

2 个答案:

答案 0 :(得分:3)

  

根据我的研究,for..in循环中键的顺序应该是未定义/不可靠的

未定义,是的。

  
      
  • 但是,如果不受干扰,应按插入顺序
  •   

不,你是第一次是对的:它未定义。即使在ES2015(又名" ES6")及更高版本(确实为其他一些操作提供属性订单)中,旧操作for-inObject.keys也不需要遵循为新的。

在其他操作(Object.getOwnPropertyNamesJSON.serialize,...)中,订单(defined here)不是纯粹的广告订单:名称为的属性数组索引根据规范的定义*首先按数字顺序排列。大多数主要的JavaScript引擎都更新了它们对for-in的处理以匹配它们对这些新操作的处理(许多已经对数组索引进行了不同的处理,但它们在是否将它们放在非数组索引之前或之后都有所不同),但同样,它是未定义的,你不应该依赖它。

如果您想要纯粹的广告订单,ES2015的Map会提供,无论密钥的价值如何。物体不是。

以下是使用Map的示例:



const map = new Map([
  ['2', { name: 'bus',  price: 10 }],
  ['3', { name: 'foot', price: 0 }],
  ['1', { name: 'taxi', price: 100 }]
]);
for (const entry of map.values()) { // bus, foot, taxi
  console.log(entry.name);
}




* The spec's definition"数组索引"是:

  

整数索引是一个字符串值属性键,它是一个规范数字字符串(见7.1.16),其数值为+0或正整数≤2 53 -1 数组索引是整数索引,其数值 i 在+0≤i<1的范围内。 2 32-1

答案 1 :(得分:1)

实际上,当键是数字时,javascript对象按插入顺序除以键。这可能是因为需要按键排序进行数组迭代(数组也是对象)。

所以,你的选择是 - 尊重标准并使用ES6 Map或对象数组来保证迭代顺序 - 让您的密钥始终为非数字,并希望获得最佳