为什么Object中的元素会自动排序

问题描述

某日开发小姐姐在维护一个老项目,突然测试反馈展示的顺序有问题了,一脸懵逼?,我一行代码没用动呢,咋回事,先看问题

服务端返回数据,期望展示顺序和服务端返回数据保持一致

const carTypes = [
  {
      "typeName":"新能源",
      "typeNo":9
  },
  {
      "typeName":"出租车",
      "typeNo":1
  },
  {
      "typeName":"中巴车",
      "typeNo":6
  },
  {
      "typeName":"自动驾驶",
      "typeNo":16
  },
]
复制代码

由于历史逻辑,代码中把数组对象改造成了 通过typeNo作为索引的对象格式

 const carServiceMap = {}
 Object.keys(carTypes).forEach((key) => {
     carServiceMap[allBizs[key].typeNo] = allBizs[key].typeName;
 });
 console.log(carServiceMap) // 会输出什么?
复制代码

看到这里,请动动你的小脑袋,carServiceMap输出是怎样的?你的答案是不是这样的?

{
	9:'新能源',
	1:'出租车',
	6:'中巴车',
	16:'自动驾驶'
}
复制代码

如果是的话,那恭喜你答错啦!!正确答案应该是这样的

{	
	1:'出租车',
	6:'中巴车',
	9:'新能源',
	16:'自动驾驶'
}
复制代码

发现了么,根据索引自动排序了,为什么对象内部会根据索引自动排序呢

问题原因

具体原因:262.ecma-international.org/6.0/#sec-or…

翻译:

9.1.12 [[OwnPropertyKeys]]()

调用 O 的 [[OwnPropertyKeys]] 内部方法时,采取以下步骤:  

    1.使 keys 变为一个空的 List

    2.对于整数类型的 O 的每个自己的属性键 P,按照数字索引升序,放到属性列表中
 
      a. 将 P 作为 keys 的最后一个元素。

    3.对于 String 类型但不是整数索引的 O 的每个自己的属性键 P,按照属性的创建时间升序,放到属性列表中
    
      a. 将 P 作为 keys 的最后一个元素。

    4.对于 Symbol 类型的 O 的每个自己的属性键 P,按照属性的创建时间升序,放到属性列表中
    
      a. 将 P 作为 keys 的最后一个元素。

    5.返回 keys。
复制代码

解决方案:

  • 直接使用数组

  • 一定要转化为对象的时候,使用map

     const carServiceMap = new Map()
     Object.keys(arr).forEach((key) => {
         carServiceMap.set(arr[key].typeNo,arr[key].typeName)
     })
     for (var [key, value] of carServiceMap) {
         console.log(key, value);
     }
    复制代码

参考:

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享