从一道前端面试题,谈 JS 对象存储特点和运算符执行顺序

本文大纲

今天来看一道前端面试的代码输出题。

面试官提供了一段Javascript代码,要求给出这段代码运行后的输出结果。

constobj={a:0,};obj['1']=0;obj[++obj.a]=obj.a++;constvalues=Object.values(obj);obj[values[1]]=obj.a;console.log(obj);

先分析这道题前,先补充两个个前置知识点。

知识点一:对象的常规属性 (properties) 和排序属性 (elements)

先来看下面一段代码:

constobj={};obj['b']='b'obj[100]='100';obj[1]='1';obj['a']='a';obj[50]='50';obj['c']='c';for(constkeyinobj){console.log(`key:${key}value:${obj[key]}`)}/** * 打印结果如下: key: 1 value: 1 key: 50 value: 50 key: 100 value: 100 key: b value: b key: a value: a key: c value: c */

观察下打印的数据,很明显属性的设置顺序并不是打印的顺序,比如b属性是第一个设置的,打印结果却排在100后面,仔细分析他们的打印规律,可以得到如下特点:

  1. 数字类的属性不管设置的顺序先后,都会被优先打印,而且是按照从小到大的升序进行打印的。
  2. 字符类属性会按照设置的顺序进行打印,上面我们是按照bac的顺序进行设置的,打印顺序也是如此。

为什么会出现这样的结果呢?

这是因为 ECMAScript 规范中定义了数字属性应该按照索引值大小升序排列,字符串属性根据创建时的顺序升序排列。在V8中数字属性被称为elements,字符串属性被称为properties。之所以这样设置,主要是为了提升访问性能。elements对象中会按照顺序存放数字属性,类似于数组的存储,这样查询的效率当然就很高了。

知识点二:JavaScript 运算符的执行顺序

JavaScript中最常见运算符如下(运算顺序从高到低排列):

  • 对象属性访问,比如obj.aobj['a']
  • 递增/递减,比如a++(后置递增) 或++a(前置递增)。
  • 算术,比如a + 1
  • 比较,包括<(小于)、>(大于)、<=(小于等于)、>=(大于等于),比如a > 3
  • 相等,包括==粗略相等,===严格相等,!==粗略不等,!==严格不等,比如a == 1
  • 逻辑,也就是与或非,&(与)、|(或)、!(非),比如a && b
  • 三元,比如flag ? '1' : '0'
  • 赋值,比如a = 1

对于单个赋值语句LHS = RHS的求值,根据ECMAScript规范(ECMA-262, AssignmentExpression evaluation),对于LeftHandSideExpression = AssignmentExpression,其计算顺序如下:

  • 第一步,先得到一个引用(Reference),即“要写入的位置”,也就是Evaluate LeftHandSideExpression
  • 第二步,再计算右侧的值,Evaluate AssignmentExpression
  • 最后将第二步得到的值写入第一步的引用当中。

也就是说,对于LHS = RHS这样的赋值表达式,其计算顺序是左侧先求值(为了知道写到哪),右侧后求值(为了知道写什么),最后将右侧的值写入左侧。

📌 注意:这里说的“左侧求值”不是求它的值,而是求它的“位置”(比如属性名、变量名等)。例如对于obj[++obj.a],要确定属性名,就必须先执行++obj.a

写个简单例子:

constobj={geta(){console.log('获取 a 的值');return1;},getb(){console.log('获取 b 的值');return2;}}obj[++obj.a]=obj.b++;console.log('obj: ',obj);

我们前面说过,运算符顺序是对象属性访问 > 递增/递减 > 赋值,对于赋值运算符LHS = RHS,会先求出左侧LHS引用(Reference),再计算右侧RHS的值,最后将右侧的值赋值给左侧的引用。所以用这个逻辑来分析下这段代码的执行顺序:

  • 第一步,先取obj.a的值, 取到的值为1, 然后执行前置递增++obj.a,结果为2,然后程序就知道要往obj2属性上赋值了。
  • 第二步,然后再取obj.b的值,执行后置递增obj.b++,右侧计算的值为2
  • 最后把右侧计算的结果值2赋值给obj[2]属性。

逐行分析代码执行过程

了解了这两个知识点后,让我们来逐行解析下这段代码。

constobj={a:0,};obj['1']=0;obj[++obj.a]=obj.a++;constvalues=Object.values(obj);obj[values[1]]=obj.a;console.log(obj);
  1. 首先,我们定义了一个对象obj,它有一个属性a,值为0
constobj={a:0,};
  1. 接下来,我们给obj添加了一个属性1,值为0,此时对象中有两个属性,a1
obj['1']=0;

由于数字属性会排在前面,此时obj的值为:

{"1":0,"a":0,}
  1. 然后会执行obj[++obj.a] = obj.a++,前面我们分析过运算符的优先级,先执行左侧++obj.a得到1,然后执行右侧obj.a++, 由于是后置递增,所以右侧的值为1,执行赋值后,obj的值为:
{"1":1,"a":2,}
  1. 经过Object.values(obj)后,values的值为[1, 2]
  2. 执行obj[values[1]] = obj.a,转换后就是obj[2] = 2obj的值变为:
{"1":1,"2":2,"a":2,}

这就是最终的输出结果了。

小结

该题主要考察两个知识点:

  1. JavaScript对象中,属性的设置顺序并不一定是循环打印顺序,在V8中,数字类的属性在被称为elements(按从小到大排列存储),字符类属性被称为properties(按添加顺序存储)。
  2. JavaScript运算符的运算顺序是对象属性访问 > 递增/递减 > 赋值,对于赋值运算符LHS = RHS,会先求出左侧LHS引用(Reference),再计算右侧RHS的值,最后将右侧的值赋值给左侧的引用。

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

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

相关文章

在RabbitMQ中,怎么确保消息不会丢失?

为了确保消息不会丢失&#xff0c;可以从以下3个方面解决&#xff1a; 1.在创建队列的时候设置durable为true&#xff0c;发布消息的时候设置delivery为2&#xff0c;从而确保队列和消息都是持久的。 这样&#xff0c;就算是RabbitMQ服务器重启也不会造成消息的丢失。 2.开启发…

深度学习毕设项目:基于python的印刷体数字和字母识别基于python深度学习的印刷体数字和字母识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

大数据领域Zookeeper的集群配置自动化工具推荐

大数据基石的"自动建筑师"&#xff1a;Zookeeper集群配置自动化工具深度解析 关键词 Zookeeper集群、配置自动化、Ansible、Kubernetes Operator、云原生运维、分布式协调、故障容错 摘要 在大数据生态中&#xff0c;Zookeeper作为分布式系统的"协调大脑"&…

【交通标示识别】模板匹配雾霾交通标示识别【含GUI Matlab源码 14873期】

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;Matlab武动乾坤博客之家&#x1f49e;…

PO、VO、BO、DTO、DAO、POJO有什么区别?

PO&#xff08;Persistent Object&#xff09;持久化对象&#xff0c;主要用于和数据库交互&#xff0c;是数据库数据在内存中的镜像。 VO&#xff08;View Object&#xff09;视图对象&#xff0c;和前端展示强相关&#xff0c;按需组装前端需要的字段。 BO&#xff08;Busine…

MYSQL_安装与配置(超详细,仅需一篇就能帮你成功安装MYSQL)

上一篇博客相信大家都已经了解到博主要讲那个数据库了&#xff0c;跟着博主的步伐一起来配置和安装数据库吧&#xff01;&#xff01;&#xff01; **1.**使用Installer安装 1.1 下载最新版本Installer 官下载8.0.X的最新版本 &#xff0c;址&#xff1a;https://dev.mysql.…

ArcGIS Pro3.5.2安装包+安装详细教程+系统需求

文章将包括系统安装需求说明软件包分享安装教程 先前版本请看&#xff1a; ArcGIS Pro稳定版 3.0.2 破解安装软件分享测试说明 ArcGIS Pro 3.1.5 破解安装软件分享测试说明 ArcGIS Pro3.3.2安装详细教程旧版本直接升级还是卸载旧版本再装&#xff1f; 一、系统安装需求升级…

【课程设计/毕业设计】基于 python的CNN深度学习的遥感图片识别沙漠湖泊和森林

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

MySQL进程CPU 飙升900%,领导让我查什么原因?

说一下问题&#xff1a;CPU飙升200% 以上是生产容易发生的场景场景:1&#xff1a;MySQL进程飙升900%大家在使用MySQL过程&#xff0c;想必都有遇到过CPU突然过高&#xff0c;或者达到200%以上的情况。数据库执行查询或数据修改操作时&#xff0c;系统需要消耗大量的CPU资源维护…

ArcGIS Pro查看多期数据变化!卷帘+多地图联动齐上架

之前介绍了ArcGIS效果工具条实现查看两期数据变化。 那么&#xff0c;如果在ArcGIS Pro中又该如何操作呢&#xff1f;ArcGIS Pro中其实有对应的卷帘效果与比较功能&#xff01;一样可以把卷帘和透明度用起来。 多期数据源的加载查看&#xff1a; 2025年最新&#xff08;全球&a…

Stream流式编程 中间操作和终端操作介绍

一、先立心智模型&#xff1a;Stream 到底是什么&#xff1f; Stream 不是集合&#xff0c;不存数据&#xff0c;不改数据。 它是&#xff1a; 对数据源的一次性、惰性的、函数式“处理流程描述” 三点必须刻在脑子里&#xff1a; 惰性执行&#xff1a;中间操作不执行&#x…

【苹果分级】基于matlab GUI机器视觉苹果质量检测及总分级系统【含Matlab源码 14878期】

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到海神之光博客之家&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49…

【课程设计/毕业设计】基于深度学习的印刷体数字和字母识别基于python深度学习的印刷体数字和字母识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

深度学习计算机毕设之机器学习基于CNN深度学习的遥感图片识别沙漠湖泊和森林

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

ArcGIS土地利用现状图制作全流程

将之前《ArcGIS Pro从0到1制作广东省土地利用现状图》直播回重新录制一遍给大家学习。详见下方视频教学 主要涉及的内容包括&#xff1a;ArcGIS土地利用现状图全流程教学&#xff08;从零数据下载、镶嵌、裁剪、属性表连接整理、面积区域汇总计算、地图全流程制作&#xff09; …

Merge3D 三维引擎中 GeoJSON 数据加载的整体设计

你想分析Merge3D&#xff08;融合引擎&#xff09;三维引擎中GeoJSON数据加载的整体设计&#xff0c;并确认是否有一个统一的类来支持点、线、面等所有几何类型的GeoJSON数据加载。 Merge3D GeoJSON 加载核心实现原理 Merge3D 中 GeoJsonLayer 能一站式支持点、线、面&#xff…

K8S安装指南与核心操作命令汇总

在云原生时代&#xff0c;Kubernetes&#xff08;简称K8S&#xff09;已成为容器编排的事实标准&#xff0c;无论是企业级应用部署还是个人技术学习&#xff0c;掌握K8S的安装与基础操作都是必备技能。本文将从安装前置准备、具体安装步骤&#xff08;以主流的kubeadm方式为例&…

企业知识管理新范式:用ChatWiki+大模型实现“一问即答“[必学收藏]

ChatWiki是一款企业级AI知识库构建平台&#xff0c;通过四步简单操作&#xff08;接入AI模型、创建知识库、配置AI机器人、实现智能应答&#xff09;&#xff0c;将分散的企业文档转化为可对话的智能资产。它解决了知识孤岛、更新低效和交互割裂三大痛点&#xff0c;适用于新员…

15_嵌入式C与控制理论入门:控制算法的定点数优化与精度平衡

嵌入式C与控制理论入门:控制算法的定点数优化与精度平衡 做嵌入式控制开发的你,大概率遇到过这种窘境:精心设计的PID、模糊控制算法,在PC上用浮点数仿真时效果拉满,可移植到STM32、TI C2000等MCU后,要么运算速度慢到突破实时控制阈值,要么因MCU缺少浮点运算单元(FPU)导…

新下证美国外观专利:42款亚马逊侵权高危新品,跨境卖家立即自查!

2025 年 12 月 30 日&#xff0c;美国专利局集中公开了一批外观专利授权公告&#xff0c;涵盖家居用品、母婴玩具、宠物用品、电子设备等四大类43款产品。跨境卖家销售同款或近似款产品时&#xff0c;需警惕侵权风险。以下专利均于 2025 年 12 月 30 日正式授权&#xff0c;涵盖…