JavaScript对象键序问题解析

问题的发现:

我有一个接口返回一个json数据浏览器network里的Response里是从大到小排。
在这里插入图片描述
但Preview就是反过来的
在这里插入图片描述

问题的描述:

上面那个让我发现浏览器处理对象或者json是会对其键值对做排序!!!

在JavaScript中,对象键的顺序问题源于语言规范:ES6之前对象键序没有明确规定,ES6之后虽然规定了自有属性的枚举顺序,但控制台输出可能因浏览器实现而异。

您观察到的现象是正常的:当使用console.log(data)时,浏览器控制台可能会按照以下规则显示对象:

数字键按数值升序排列

字符串键按创建顺序排列

但某些浏览器控制台(如Chrome)会对所有键进行字母排序后再显示

问题的复现:

示例一:key是一个字符串

let obj = {
      "2023-08-30": "8888",
      "2023-08-10": "5555",
      "2023-08-08": "6666",
      "2023-06-02": "7777",
      "2023-06-01": "7777",
    };
     // let obj = {
    //   "3-3": "cc",
    //   "3-2": "bb",
    //   "3-1": "aa",
    // };
    console.log("原数据:",obj);
    console.log("key数组:", Object.keys(obj));

示例一:key是一个日期字符串结果截图
结果分析:
1.打印出的对象和原数据不一致被正序排序了
2.使用for in或者 Object.keys时键值的顺序没有发生变化

示例二:key是一个数字

   let obj = {
      20230830: "8888",
      20230810: "5555",
      20230808: "6666",
      20230602: "7777",
      20230601: "7777",
    };

    console.log("原数据:", obj);
    console.log("key数组:", Object.keys(obj));

示例二:key是一个数字
结果分析:
1.打印出的对象和原数据不一致被正序排序了
2.使用for in或者 Object.keys时键值的顺序发生变化了

示例三:key是一个字母

   let obj = {
      c: "cc",
      b: "bb",
      a: "aa",
    };
    //   let obj = {
    //       "c": "cc",
    //       "b": "bb",
    //       "a": "aa",
    //    };

    console.log("原数据:", obj);
    console.log("key数组:", Object.keys(obj));

 示例三:key是一个字母

结果分析:
1.打印出的对象和原数据不一致被正序排序了
2.使用for in或者 Object.keys时键值的顺序没有发生变化

总结:

经过上面的三个示例可得出:
数字字符串键在对象属性遍历时会按数值升序排列。
非数字字符串键按照创建顺序排列。
使用Map可以完全保留插入顺序。

需要注意的是JSON.parse也使用这个规则!

关键结论:

对象键序问题原因:

控制台显示可能对键进行字母排序

JavaScript规范中对象键的顺序是:整数索引 > 字符串键(按创建顺序)> Symbol键

但字符串键中的数字字符串会被特殊处理

特殊处理的规则如下:

具体来说,ECMAScript规范规定,对象中的数字键(即数字字符串键)会按照数值大小升序排序,而非数字字符串键则按照创建顺序排列。

特殊处理规则:
‌数字字符串键‌:会被视为数字索引,在对象属性遍历时(如使用Object.keys、for…in循环等)会按照数值升序排列。

‌非数字字符串键‌:按照属性添加到对象的先后顺序排列(从ES6开始,普通对象保持字符串键的创建顺序,但数字字符串键仍然会被特殊排序)。

const obj = {
  "100": "一百",
  "2": "二",
  "name": "张三",
  "1": "一",
  "age": 20
};

console.log(Object.keys(obj));
// 输出: [ '1', '2', '100', 'name', 'age' ]

注意:
只有看起来像非负整数的字符串(例如"123"、“0”)才会被当作数字键处理。像"001"、"123a"这样的字符串不会被当作数字键,而是普通字符串键。
在ES6之前,不同JavaScript引擎对非数字字符串键的遍历顺序是不一致的。但从ES6开始,规范要求非数字字符串键按照创建顺序排列,而数字字符串键按照数值升序排列。

是否会影响使用:

直接通过键访问属性:不受影响

遍历对象属性(for…in/Object.keys):顺序可能不符合预期

依赖对象键序的业务逻辑:可能有风险

推荐解决方案:

使用Map对象保持插入顺序

使用数组显式存储键的顺序

在遍历前对键进行排序(如按日期倒序)

还需要注意的是控制台打印对象时可能也会出现不一致的情况,详情可以看:js 控制台打印对象,对象点开后里面属性没值,展开后有值(object展开和收起值不一致)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

崽崽的谷雨

漫漫前端路,摸爬滚打

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值