【问题标题】:Iteration order of for.in – not by insertion (any more?)for.in 的迭代顺序——不是插入(还有吗?)
【发布时间】:2017-07-24 13:16:02
【问题描述】:

根据我的研究,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 排序?

【问题讨论】:

  • 如果您需要订购它们,请在Object.values() 上使用sort()
  • 我猜可能会发生某种内部优化,它看起来像一个数组
  • 是的 - 如果您添加一个不是数字的键,它会按预期工作
  • 结果是订单未定义,永远不应该依赖

标签: javascript sorting for-in-loop


【解决方案1】:

根据我的研究,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 或正整数 ≤ 253 -1数组索引是一个整数索引,其数值i在+0 ≤ i 32-1范围内。

【讨论】:

  • 感谢您的精彩回答!地图看起来像我最好的新朋友 :)
【解决方案2】:

在实践中,当键是数字时,javascript 对象会按插入顺序 except 中的键进行迭代。这可能是由于需要按键排序的数组迭代(数组也是对象)。

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

【讨论】:

  • 我不喜欢“希望最好”的方法 - 太老了 :) 映射它!
猜你喜欢
  • 1970-01-01
  • 2011-04-08
  • 1970-01-01
  • 2011-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
相关资源
最近更新 更多