社区编辑申请
注册/登录
聊聊JS中Object的Keys是无序的吗?
开发 前端
在 ES6 之后 Object 的键值对按照自然数、非自然数和 Symbol 进行排序,自然数是按照大小升序进行排序,其他两种都是按照插入的时间顺序进行排序。

在最开始学习 JavaScript 时,我一直被灌输 Object 中的 Key 是无序的,不可靠的,而与之相对的是 Map 实例会维护键值对的插入顺序。

「But,Object 的键值对真的是无序的吗?」实际上在 ES2015 以后,Object.keys 的规则变了:

在一些现代的浏览器中,keys 输出顺序是可以预测的!

Key 都为自然数:

注意这里的自然数是指正整数或 0,如果是其他类的 Number —— 浮点数或者负数 —— 都会走到下一组类型里,像NaN或者Infinity这种也自然归到下一个类型里,但是像科学记数法这个会稍微特殊一点,感兴趣的同学可以自己试一下。

总结来说,就是当前的 key 如果是自然数就按照自然数的大小进行升序排序。

const objWithIndices = {
23: 23,
'1': 1,
1000: 1000
};

console.log(Reflect.ownKeys(objWithIndices)); // ["1", "23", "1000"]
console.log(Object.keys(objWithIndices)); // ["1", "23", "1000"]
console.log(Object.getOwnPropertyNames(objWithIndices)); // ["1", "23", "1000"]

包括在 for-in 循环的遍历中,keys 也是按照这个顺序执行的。

Key 都为 String:

如果 key 是不为自然数的 String(Number 也会转为 String)处理,则按照加入的时间顺序进行排序。

const objWithStrings = {
"002": "002",
c: 'c',
b: "b",
"001": "001",
}

console.log(Reflect.ownKeys(objWithStrings)); // ["002", "c", "b", "001"]
console.log(Object.keys(objWithStrings));// ["002", "c", "b", "001"]
console.log(Object.getOwnPropertyNames(objWithStrings));// ["002", "c", "b", "001"]

Key 都为symbol

const objWithSymbols = {
[Symbol("first")]: "first",
[Symbol("second")]: "second",
[Symbol("last")]: "last",
}

console.log(Reflect.ownKeys(objWithSymbols));// [Symbol(first), Symbol(second), Symbol(last)]
console.log(Object.keys(objWithSymbols));// [Symbol(first), Symbol(second), Symbol(last)]
console.log(Object.getOwnPropertyNames(objWithSymbols));// [Symbol(first), Symbol(second), Symbol(last)]

如果 Key 都为 Symbol,顺序和 String 一样,也是按照添加的顺序进行排序的。

如果是以上类型的相互结合

const objWithStrings = {
"002": "002",
[Symbol("first")]: "first",
c: "c",
b: "b",
"100": "100",
"001": "001",
[Symbol("second")]: "second",
}

console.log(Reflect.ownKeys(objWithStrings));
// ["100", "002", "c", "b", "001", Symbol(first), Symbol(second)]

结果是先按照自然数升序进行排序,然后按照非数字的 String 的加入时间排序,然后按照 Symbol 的时间顺序进行排序,也就是说他们会先按照上述的分类进行拆分,先按照自然数、非自然数、Symbol 的顺序进行排序,然后根据上述三种类型下内部的顺序进行排序。

Recap

  • 在 ES6 之前 Object 的键值对是无序的;
  • 在 ES6 之后 Object 的键值对按照自然数、非自然数和 Symbol 进行排序,自然数是按照大小升序进行排序,其他两种都是按照插入的时间顺序进行排序。

References:

「Property order is predictable in JavaScript objects since ES2015」: https://www.stefanjudis.com/today-i-learned/property-order-is-predictable-in-javascript-objects-since-es2015

「The traversal order of object properties in ES6」: http://2ality.com/2015/10/property-traversal-order-es6.html#traversing-the-own-keys-of-an-object

责任编辑:武晓燕 来源: Tecvan
相关推荐

2022-05-24 08:21:16

数据安全API

2022-05-16 08:50:23

2022-05-10 08:59:25

2022-04-02 10:23:12

MySQL数据库

2022-05-16 07:35:21

Windows远程桌面远程服务器

2022-03-17 08:54:59

软件系统重构

2022-04-11 07:50:58

2022-04-14 12:24:20

2022-03-29 08:30:47

2022-04-20 07:48:09

微服务链路服务器

2022-03-31 07:52:01

Java多线程并发

2022-04-22 13:04:43

微软Windows 10

2022-03-31 16:47:30

mysqlcount面试官

2022-04-05 13:10:15

consul分布式高可用

2022-04-07 09:50:07

DDR5内存CPU

2022-03-22 10:24:48

Linux开源Elasticsea

2022-03-17 08:30:28

Python私有属性私有方法

2022-03-31 08:21:14

数据库缓存双写数据一致性

2022-03-29 10:39:10

2022-02-09 16:23:07

同话题下的热门内容

让程序员心动的11种新编程语言Flutter vs ReactJS:2022年应该选哪个?再有人问你什么是分库分表,直接把这篇文章发给他前端配置化真香~上班又多了60%的摸鱼时间2022年值得使用的 Node.js 框架HTTP 的缓存为什么这么设计?如何加快Java中大型集合的处理前端监控的搭建步骤,别再一头雾水了!

编辑推荐

太厉害了,终于有人能把TCP/IP协议讲的明明白白了!牛人5次面试腾讯不成功的经验HBase原理–所有Region切分的细节都在这里了Javascript如何监听页面刷新和关闭事件如何搭建一个HTTPS服务端
我收藏的内容
点赞
收藏

51CTO技术栈公众号