JavaScript中对象属性的顺序问题

        我们首先需要了解的是,在JavaScript中,对象的属性名只能是字符串或者symbol。假设我们给将属性名设置为非string和symbol类型,都会被隐式转换成字符串。

let a = {1: 1,true: true,
}
// 等同于
let a = {'1': 1,'true': true,
}a[{}] = {}
a[()=>{}] = 'fun'
// 等同于
a["[object Object]"] = {}
a["()=>{}"] = 'fun'

        考虑如下代码:

let a = {};
a[0] = 0;
a['b'] = 'b';
a[Symbol('symbol2')] = 'symbol1';
a[2] = 2;
a[Symbol('symbol1')] = 'symbol2';
a[{}] = '{}'
a['a'] = 'a';
a['1'] = 1;console.log('Object.keys(a)', Object.keys(a));
console.log('Reflect.ownKeys(a)', Reflect.ownKeys(a));

题外话:

        Symbol 类型的属性在 JavaScript 中被认为是不可枚举的。因此如果简单通过Object.keys或for in循环所有key的话。是不会得到symbol类型的属性名的。但是我们可以通过Reflect.ownKeys()输出所有属性名。
        Reflect.ownKeys方法用于返回对象的所有属性,基本等同于Object.getOwnPropertyNames与Object.getOwnPropertySymbols之和。

        getOwnPropertyNames:用于返回一个由指定对象的所有自身属性(包括不可枚举属性但不包括Symbol值作为名称的属性)的属性名(包括不可枚举属性)组成的数组。这个方法在ES5中就引入了。

        getOwnPropertySymbols:这是一个ES6(ECMAScript 2015)中引入的方法。用于返回一个由指定对象的所有自身Symbol值的属性键组成的数组。这个方法不会返回字符串键或不可枚举的属性键。

上述代码输出的对象a的所有key数组。输出结果如下:

可以看到,顺序并不是完全按照插入顺序来排列的。属性直接也是有区别的。

在ES6及之后的版本中,对象的属性迭代顺序大致遵循以下规则:

        1、数值属性:首先会迭代对象的所有数值键,按照数值的升序进行。

        2、字符串属性:然后按字符串的插入顺序依次迭代字符串属性

        3、symbol属性:再然后按symbol的插入顺序依次迭代symbol属性

        4、继承属性:当一个对象上有自己的属性,并且还继承一些属性的时候。整体也是按照上述三条规则排序的,但是插入顺序可能需要注意。这里暂不考虑这种特殊复杂情况。

需要注意的是,尽管上述规则在大多数现代JavaScript引擎中得到了遵守,但ECMAScript标准并没有强制要求这样的顺序。因此,为了编写健壮的代码,最好不要依赖特定的属性迭代顺序。我们做为一个知识点了解即可。

例如:字符串和symbol的顺序可能因引擎差异会按照其UTF-16编码单元的字典顺序进行排序。


深入了解,这里引用网上一些知识点:

        在V8引擎中,对象的属性会根据其类型和使用情况进行不同的存储和处理。数字属性在V8中通常被称为“elements”,而字符串属性则被称为“properties”。

        对于迭代对象属性时的顺序,V8引擎会遵循ECMAScript规范中的规则。根据规范,可索引的属性(通常是数字键)会按照索引值大小升序排列,而命名属性(通常是字符串键)则根据创建的顺序升序排列

        在V8引擎中,数字属性(也被称为“elements”或“索引属性”)是按顺序迭代的关键在于其底层的存储机制。

        V8使用了一种优化的数据结构来存储对象的数字属性,这种结构通常被称为“元素数组”或“属性数组”。当对象主要包含连续的数字键时,V8会将这些属性存储在一个连续的内存区域中,以便高效地按索引访问和迭代。

        这种数组结构允许V8引擎直接通过索引值来快速查找和访问属性。当迭代数字属性时,V8引擎可以简单地遍历这个数组,按照索引值的升序来访问每个属性。

        这种机制使得数字属性的迭代变得非常高效,因为引擎可以直接利用数组的连续内存布局来按顺序访问每个元素,而无需进行复杂的查找或排序操作。

需要注意的是,这种优化主要适用于连续的数字键。对于非数字键或稀疏的数字键(即存在大量未定义的索引),V8可能会采用其他的数据结构或策略来存储和迭代属性,以确保性能和内存使用的平衡。

        总之,V8引擎通过利用专门的元素数组来存储和迭代数字属性,实现了按索引值升序的迭代顺序。这种机制使得在处理包含连续数字键的对象时,能够高效地按顺序访问和迭代这些属性。

        经过简单测试,在同时存储10w个属性的情况下,即使存储10w不连续的数字属性,也要比10w个字符串平均快2-3倍左右。要是存储连续的数字,则快10倍不止了

let b = {};
console.time('b1')
for (let index = 0; index < 10 * 10000; index++) {b[Math.floor(Math.random() * 100000)] = index;// b[index] = index;
}
console.timeEnd('b1')
b = {};
console.time('b2')
for (let index = 0; index < 10 * 10000; index++) {b[`-${index}`] = -index
}
console.timeEnd('b2')


        到这里就结束了,不过还有个骚操作值得一说

        假设有一个没有重复元素的数组需要排序的话。我们就可以遍历一遍数组,将这些数据依次添加到对象中,对象则会帮我们做好排序了,然后再输出对象的所有key。理论上是比任何排序方法都要快的。但是空间复杂度就是是O(n)了。哈哈,还是不建议这样做了。如上所述,但凡引擎修改了规则,完蛋。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/279952.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Elasticsearch】windows安装elasticsearch教程及遇到的坑

一、安装参考 1、安装参考&#xff1a;ES的安装使用(windows版) elasticsearch的下载地址&#xff1a;https://www.elastic.co/cn/downloads/elasticsearch ik分词器的下载地址&#xff1a;https://github.com/medcl/elasticsearch-analysis-ik/releases kibana可视化工具下载…

vue 基于elementUI/antd-vue, h函数实现message中嵌套链接跳转到指定路由 (h函数点击事件的写法)

效果如图&#xff1a; 点击message 组件中的 工单管理&#xff0c; 跳转到工单管理页面。 以下是基于vue3 antd-vue 代码如下&#xff1a; import { message } from ant-design-vue; import { h, reactive, ref, watch } from vue; import { useRouter } from vue-router; c…

将FastSAM中的TextPrompt迁移到MobileSAM中

本博文简单介绍了SAM、FastSAM与MobileSAM,主要关注于TextPrompt功能的使用。从性能上看MobileSAM是最实用的,但其没有提供TextPrompt功能,故而参考FastSAM中的实现,在MobileSAM中嵌入TextPrompt类。并将TextPrompt能力嵌入到MobileSAM官方项目提供的gradio.py部署代码中,…

算法体系-11 第十一节:二叉树基本算法(上)

一 两链表相交 1.1 题目描述 给定两个可能有环也可能无环的单链表&#xff0c;头节点head1和head2。请实现一个函数&#xff0c;如果两个链表相交&#xff0c;请返回相交的 第一个节点。如果不相交&#xff0c;返回null 【要求】 如果两个链表长度之和为N&#xff0c;时间复杂…

强化PaaS平台应用安全:关键策略与措施

PaaS&#xff08;平台即服务&#xff0c;Platform-as-a-Service&#xff09;是一种云计算服务模式&#xff0c;可以为客户提供一个完整的云平台&#xff08;硬件、软件和基础架构&#xff09;以用于快捷开发、运行和管理项目&#xff0c;从而降低了企业云计算应用的高成本和复杂…

.NET高级面试指南专题十七【 策略模式模式介绍,允许在运行时选择算法的行为】

介绍&#xff1a; 策略模式是一种行为设计模式&#xff0c;它允许在运行时选择算法的行为。它定义了一系列算法&#xff0c;将每个算法封装到一个对象中&#xff0c;并使它们可以互相替换。这使得算法可独立于使用它的客户端变化。 原理&#xff1a; 策略接口&#xff08;Strat…

源码部署LAMP架构

LAMP 文章目录 LAMP1. lamp简介2. web服务器工作流程2.1 cgi与fastcgi2.2 httpd与php结合的方式2.3 web工作流程 3. LAMP平台构建3.1 安装httpd3.2 安装mysql3.3 安装php3.4 验证 1. lamp简介 有了前面学习的知识的铺垫&#xff0c;今天可以来学习下第一个常用的web架构了。 …

软件工程-第三版王立福-第1章 绪论

本书结合IEEE最新发布的软件工程体系SWEBOK&#xff0c;和IEEE/ACM软件工程学科小组公布的软件工程教育知识体系SEEK&#xff0c;北大本科生指定教材。注重基础知识的系统性&#xff0c;选材的先进性及知识的应用。2009年出版 软件开发本质的认识&#xff0c;两大技术问题&…

自存vue3 ts jump start-3 computed

computed是一个方法&#xff0c;参数可以接收一个函数&#xff0c;最终返回需要的。获取最新的因数据改变而得到的数据。

《汽车数据安全若干问题合规实践指南》正式发布(百度盘下载)

指南针对汽车数据安全的重要合规内容&#xff0c;结合汽车行业特有场景&#xff0c;参考行业最佳实践&#xff0c;提出合规实践建议。指南旨在进一步提高汽车行业数据安全保护水平&#xff0c;增强汽车企业数据安全合规保障能力&#xff0c;推动汽车数据价值安全使用&#xff0…

京津冀太阳能光伏展

京津冀太阳能光伏展是一个专门展示和推广太阳能光伏技术和产品的展览活动。该展览主要面向京津冀地区的企业、科研院校、政府机构以及普通市民&#xff0c;旨在促进太阳能光伏在京津冀地区的推广应用&#xff0c;推动清洁能源的发展。 在京津冀太阳能光伏展上&#xff0c;参展的…

Zerotier 异地组网方案初探

前言 我之前想要异地组网的话&#xff0c;一般都采用内网穿透的方法&#xff0c;但是这个内网穿透有弊端就是都是要通过公网服务器转发流量&#xff0c;对于大流量的传输就比较不方便&#xff0c;我发现了Zerotier 这个工具非常的好用&#xff0c;是基于p2p的 这是一个类似于…

高效使用 JMeter 生成随机数:探索 Random 和 UUID 算法

在压力测试中&#xff0c;经常需要生成随机值来模拟用户行为。JMeter 提供了多种方式来生成随机值&#xff0c;本文来具体介绍一下。 随机数函数 JMeter 提供了多个用于生成随机数的函数&#xff0c;其中最常用的是__Random函数。该函数可以生成一个指定范围内的随机整数或浮…

【哈希表】算法例题

目录 五、哈希表 39. 赎金信 ① 40. 同构字符串 ① 41. 单词规律 ① 42. 有效的字母异位词 ① 43. 字母异位词分组 ② 44. 两数之和 ① 45. 快乐数 ① 46. 存在重复元素 ① 47. 最长连续序列 ② 五、哈希表 39. 赎金信 ① 给你两个字符串&#xff1a;ransomNote 和 m…

Linux入门-常见指令及权限理解

目录 1、Linux背景 1.1、发展历史 1.2、开源 1.3Linux企业应用现状 2、Linux下的基本命令 2.1、ls 指令 2.2、pwd 命令 2.3、cd 命令 2.4、touch命令 2.5、mkdir 命令 2.6、rmdir 指令和 rm指令 2.7 man 指令 2.8、cp指令 2.9、mv 指令 2.10 cat 2.11 more 2…

网络学习:IPV6基础配置

目录 一、配置接口的全球单播地址 二、配置接口本地链路地址 三、配置接口任播地址 四、配置接口PMTU 配置静态PMTU&#xff1a; 配置动态PMTU&#xff1a; 五、接口配置IPV6地址示例&#xff1a; 一、配置接口的全球单播地址 全球单播地址类似于IPv4公网地址&#xff0…

个人微信开发API

安卓微信的api&#xff0c;个人微信开发API协议&#xff0c;微信 ipad &#xff0c;微信ipad协议&#xff0c;微信web版接口api&#xff0c;微信网页版接口&#xff0c;微信开发sdk&#xff0c;微信开发API&#xff0c;微信协议&#xff0c;微信接口文档&#xff0c;网页个人微…

FPGA高端项目:FPGA基于GS2971+GS2972架构的SDI视频收发+HLS图像缩放+多路视频拼接,提供4套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐本博主所有FPGA工程项目-->汇总目录本博已有的 SDI 编解码方案本方案的SDI接收发送本方案的SDI接收图像缩放应用本方案的SDI接收纯verilog图像缩放纯verilog多路视频拼接应用本方案的SDI接收OSD动态字符叠加输出应用本方案的SDI接收HLS…

docker小白第十四天之Portainer与CIG

Portainer简介 Portainer是一款轻量级的应用&#xff0c;它提供了图形化界面&#xff0c;用于方便地管理Docker环境&#xff0c;包括单机环境和集群环境。 Portainer命令安装 # 一个容器可以同时起多个-p端口&#xff0c;restartalways表示随时在线&#xff0c;重启机器后也…

麒麟系统Redis7.2哨兵集群部署

redis哨兵集群部署 1、原理 Redis 哨兵模式是指在 Redis 集群中,有一组专门的进程(即哨兵进程)负责监控主节点和从节点的状态,并在发现故障时自动进行故障转移,以保证 Redis 集群的高可用性。 Redis 提供了哨兵的命令,哨兵命令是一个独立的进程,哨兵进程会周期性地向主…