for.in 的迭代顺序——不是通过插入(还有吗?)
Iteration order of for.in – not by insertion (any more?)
根据我的研究,for..in
循环中键的顺序应该是 undefined/unreliable – 但是,如果不受干扰,应该按插入顺序排列 – 但事实并非如此:
我从数据库中获取这个数据对象,按名称排序:
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
排序的它们?
According to my research, the order of keys in a for..in loop should be undefined/unreliable
未定义,是的。
- but, if left undisturbed, should be in insertion order
不,你第一次是对的:它是未定义的。即使在 ES2015(又名 "ES6")及更高版本中,确实为某些其他操作提供了 属性 顺序,旧操作 for-in
和 Object.keys
也不需要遵循定义的顺序对于新的。
在那些其他操作(Object.getOwnPropertyNames
、JSON.serialize
、...)中,顺序 (defined here) 不是纯粹的插入顺序:名称为 [=41 的属性=]array indexes 根据规范的定义 * 按数字顺序排在第一位。大多数主要 JavaScript 引擎已经更新了它们对 for-in
的处理以匹配它们对这些新操作的处理(许多已经确实以不同方式处理数组索引,但它们在是否将它们放在非数组之前有所不同-indexes 或之后),但同样,它是未定义的,你不应该依赖它。
如果你想要纯插入顺序,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 的 "array index" 是:
An integer index is a String-valued property key that is a canonical numeric String (see 7.1.16) and whose numeric value is either +0 or a positive integer ≤ 253-1. An array index is an integer index whose numeric value i is in the range +0 ≤ i < 232-1.
实际上,javascript 对象按插入顺序按键迭代 除了 当键是数字时。这可能是因为需要进行数组迭代(数组也是对象)按键排序。
所以,你的选择是
- 尊重标准并使用 ES6 Map 或对象数组来保证迭代顺序
- 让你的钥匙永远是非数字的,并希望最好
根据我的研究,for..in
循环中键的顺序应该是 undefined/unreliable – 但是,如果不受干扰,应该按插入顺序排列 – 但事实并非如此:
我从数据库中获取这个数据对象,按名称排序:
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
排序的它们?
According to my research, the order of keys in a for..in loop should be undefined/unreliable
未定义,是的。
- but, if left undisturbed, should be in insertion order
不,你第一次是对的:它是未定义的。即使在 ES2015(又名 "ES6")及更高版本中,确实为某些其他操作提供了 属性 顺序,旧操作 for-in
和 Object.keys
也不需要遵循定义的顺序对于新的。
在那些其他操作(Object.getOwnPropertyNames
、JSON.serialize
、...)中,顺序 (defined here) 不是纯粹的插入顺序:名称为 [=41 的属性=]array indexes 根据规范的定义 * 按数字顺序排在第一位。大多数主要 JavaScript 引擎已经更新了它们对 for-in
的处理以匹配它们对这些新操作的处理(许多已经确实以不同方式处理数组索引,但它们在是否将它们放在非数组之前有所不同-indexes 或之后),但同样,它是未定义的,你不应该依赖它。
如果你想要纯插入顺序,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 的 "array index" 是:
An integer index is a String-valued property key that is a canonical numeric String (see 7.1.16) and whose numeric value is either +0 or a positive integer ≤ 253-1. An array index is an integer index whose numeric value i is in the range +0 ≤ i < 232-1.
实际上,javascript 对象按插入顺序按键迭代 除了 当键是数字时。这可能是因为需要进行数组迭代(数组也是对象)按键排序。
所以,你的选择是 - 尊重标准并使用 ES6 Map 或对象数组来保证迭代顺序 - 让你的钥匙永远是非数字的,并希望最好