之前曾在网上看到使用object.keys的时候,如果对象的key是正整数,那么他就会被进行排序,我很好奇是否是这样,而且如果用其他方法去遍历对象的key是否结果都一样.
那么,先来创建几个对象
let en={
a:1,
b:2,
d:3,
c:4,
}
let num={
1:1,
3:2,
4:3,
2:4,
}
那么对象创建完毕了,来试试看遍历它的key
console.log("Object.keys(keys):",Object.keys(en));
console.log("Object.getOwnPropertyNames(keys):",Object.getOwnPropertyNames(en));
let listEn=[]
for(let key in en){
listEn.push(key);
}
console.log("listEn:",listEn);
使用了三种方法,分别是object.keys,object.getOwnPropertyNames以及for in.
现在,执行一下代码,看看结果如何.
看起来很正常,key是字符的情况下是按照创建对象时的属性顺序进行显示的.
那么接下来试试看正整数为key的那部分
很神奇,三种方法显示的结果都是一样的,按照正整数顺序展示了,与创建时的顺序无关了.
再进行几个测试
字符数字:
数字+字母:
无小数浮点数:
**
**
有小数浮点数:
所以只有在key为实际为正整数的情况下,对象内部的属性顺序才会被排序.
什么的问题解决了,接下来是为什么.
答案在 ECMA262规范 中,不过是纯英文,以我英语四级的水平看起来有那么一些折磨,所以我又去百度了一下.
找到了这篇文章 ,然后在ECMA规范中有说到,object.keys的原理,如下图所示
先将对象转成obj,然后通过Enum...方法获取到属性列表,并赋值给array.
然后getOwnPropertyNames的原理是先将对象转成object,然后使用迭代器一个个遍历出来.
从上面两个图中可以看到,这两种方法都用到了OwnPropertyKeys,然后发现这个方法就是用来获取属性列表的.
所以我猜测,所有obj的获取属性,最终都是调用以下的OwnPropertyKeys方法. 这就是为什么,用三种方法的结果都是一样的情况,因为最底层的本质都是同一个方法.
而关于ownPropertyKeys的各种情况中,关于整数情况的处理如下:
所以这就是为什么使用正整数的时候,顺序会被重新排序.
顺带一提,以上的排序规则同样适用与下面这几个方法.
- Object.entries
- Object.values
- for...in循环
- Object.getOwnPropertyNames
- Reflect.ownKeys
初次写这种笔记,倘若有什么问题,还望大佬们指出.