镀铬重新排序对象键,如果数字,则是正常/预期的
-
02-10-2019 - |
题
我注意到某些评估电子商务网站的鞋子大小并在屏幕上输出的代码正在弄乱Chrome的订单。
JSON可以是:
{
"7": ["9149", "9139", "10455", "17208"],
"7.5": ["9140", "9150", "10456", "17209"],
"8": ["2684", "9141", "10457", "17210"],
"8.5": ["9142", "10444", "10458", "17211"],
"9": ["2685", "9143", "10459", "17212"],
"9.5": ["10443", "9144", "10460", "17213"]
}
...哪一半会增加大小。
转换为对象并迭代键后,自然秩序被尊重,它们出现为:
7、7.5、8、8.5等
但是仅在镀铬中,“看起来”圆形数字的键 总是 首先从对象出来,因此a的输出...在循环中是:
7, 8, 9, 7.5, 8.5, 9.5 ...
Object.keys(sizes); // ["7", "8", "9", "7.5", "8.5", "9.5"]
这是测试案例: https://jsfiddle.net/wcapc46l/1/
它仅影响整数,似乎Webkit / Blink具有优化, 喜欢 数字的对象属性,也许与分支预测或其他有关。
如果将对象键带有任何字符,则该订单仍未受到影响并按预期工作-FIFO
我想我记得我读到,对物体的属性顺序没有保证,但与此同时,这对极端是烦人的,并且会造成相当大的努力来单独为Chrome用户修复它。
有任何想法吗?这可能是一个被修复的错误吗?
编辑 此外,我现在已经在V8错误跟踪器上发现了这一点:
http://code.google.com/p/v8/issues/detail?id=164
看起来眨眼不想修复此问题,并且将仍然是唯一可以做到的浏览器。
更新 webkit/blink的Hash表优化的任何内容,现在都进入了壁虎(FF 27.0.1) - http://jsfiddle.net/9htmq/ 结果是
7,8,9,7.5,8.5,9.5
. 。申请_
在钥匙返回正确 /预期订单之前。更新2017 人们仍然在投票和编辑,因此似乎不会影响
Map
/WeakMap
,Set
等(如更新的主要示例所示)
解决方案
这是V8处理关联阵列的方式。一个已知问题 问题164 但是它遵循规格,因此被标记为“按预期工作”。没有必需的订单来通过关联阵列进行循环。
一个简单的解决方法是在数字值之前用字母:例如: 'size_7':['9149','9139']
等等
该标准将在下一个ecmascript规格中改变迫使[Chrome]开发人员更改此标准。
其他提示
看来Chrome正在处理 整数 字符串好像是数字类型,当用作索引/属性名称时。
我认为依靠JavaScript实现来保留在某些情况下是对象属性的顺序,而在其他情况下(当然是Chrome)数组零件,显然是不安全的方法和枚举顺序,可能未在规格中定义。 。我建议在JSON中添加一个附加属性,以指示排序顺序:
{
"7":{"sortOrder":1,"data":["9149","9139","10455","17208"]},
"7.5":{"sortOrder":2,"data":["9140","9150","10456","17209"]}
//etc
}
他们被视为字符串,因为他们 是 字符串。我最好的建议是在所有键中使用相同的“精度”。
{"7.0":["9149","9139","10455","17208"],"7.5":["9140","9150","10456","17209"],"8.0":["2684","9141","10457","17210"],"8.5":["9142","10444","10458","17211"],"9.0":["2685","9143","10459","17212"],"9.5":["10443","9144","10460","17213"]}
因此,“ 8.0”而不是“ 8”,等。
即使那样,也没有保证,但是他们更有可能以相同的顺序出现。
为了获得更好的保证,请根据键执行排序,将值以排序顺序放入数组中。
在对象的属性上迭代时,在eCmascript规范中指定订单为未定义,并且您可能在某些环境中观察到的任何顺序不应依赖。如果您需要订单,请使用 Array
.
我认为您不能称其为错误。就像您说的那样,对物体的属性是如何分类的。
我发现使用强score.js的工作很轻松
myArray = _.sortBy(myArray, function(num){ return Math.ceil(num); });
耶! MyArray在所有浏览器中都回到了正确的顺序。
我的钥匙对我来说太重要了,无法将它们转换为弦。相反,我创建了另一个数组,该数组刚刚维护了密钥的顺序。
<?php
$origArray = valueReturnedFromFunction();
$preservedOrder = array_keys($origArray);
?>
<script>
var origArray = <?php echo json_encode($origArray)?>;
var preservedOrder = <?php echo json_encode($preservedOrder )?>;
for(i in preservedOrder){
var item = origArray[i];
...
}
</script>