Object.keys() 使用会引发的问题

本文探讨了JavaScript中Object.keys()返回顺序的规律,指出字符串和浮点数属性按创建顺序,正整数属性按数值升序。这源于V8引擎对对象属性的处理方式,它区分了常规属性和排序属性,使用隐藏类优化访问效率。对象属性的存储和排序涉及到快属性、慢属性、对象内属性等概念,以及隐藏类和形状的变化。深入理解这些机制有助于优化JavaScript代码的性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Object.keys()返回的顺序是什么?

我们理解的 Object.keys()总是会按照实际创建属性的顺序返回

当key为字符串时候,返回

let test = {
      a: 1,
      b: 2,
      d: 4,
      c: 3,
    }
    console.log(Object.keys(test))
    // 输出[ 'a', 'b', 'd', 'c' ]

把key换成浮点数,结果如下

let test = {
	  '1.0': 1,
	  '2.0': 2,
	  '4.0': 4,
	  '3.0': 3,
	}
	console.log(Object.keys(test))
	// 输出 [ '1.0', '2.0', '4.0', '3.0' ]

把key换成正整数,结果如下

 let test = {
	  [1]: 1,
	  [2]: 2,
	  [4]: 4,
	  [3]: 3,
 }
	console.log(Object.keys(test))
	// 输出 [ '1', '2', '3', '4' ]

把key换成浮点数和正整数组合,结果如下:

let test = {
	  '1.0': 1,
	  [2]: 2,
	  '4.0': 4,
	  [3]: 3,
	}
   console.log(Object.keys(test))
   //输出 [ '2', '3', '1.0', '4.0' ]

通过上面的输出,总结出现象是如果key为字符串或者浮点数的时候,会按照创建属性的顺序返回,如果是正整数会按照从小到大的顺序返回。这种情况的产生的原因是什么?

Object.keys() 返回顺序与遍历对象属性时的顺序一样,调用的 [OwnPropertyKeys] 内部方法

根据 ECMAScript 规范,在输出 keys 时会先将所有 key 为数组索引类型(正整数)从小到大的顺序排序,然后将所有字符串类型(包括负数、浮点数)的 key 按照实际创建的顺序来排序。

V8 内部是如何处理对象属性的?

V8 在存储对象属性时,为了提高访问效率,会分为常规属性(properties) 和 排序属性(elements)

排序属性(elements) ,就是数组索引类型的属性(也就是正整数类型)。
常规属性(properties) ,就是字符串类型的属性(也包括负数、浮点数)。
以上两种属性都会存放在线性结构中,称为快属性。
然而这样每次查询都有一个间接层,会影响效率,所以 V8 引入对象内属性(in-object-properties) 。

V8 会为每一个对象关联一个隐藏类,用于记录该对象的形状,相同形状的对象会共用同一个隐藏类。

当对象添加、删除属性的时候,会创建一个新的对应的隐藏类,并重新关联。

对象内属性会将部分常规属性直接放在对象第一层,所以它访问效率是最高的。

当常规属性的数量少于对象初始化时的属性数量时,常规属性会直接作为对象内属性存放。

虽然快属性访问速度快,但是从线性结构中添加或删除时执行效率会非常低,因此如果属性特别多、或出现添加和删除属性时,就会将常规属性从线性存储改为字典存储,形成慢属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值