细谈 JS 对象遍历的顺序问题

细谈 JS 对象遍历的顺序问题可能有些同学听过在 JavaScript 中遍历对象顺序不固定的这一说法 事实上 这个说法不是特别准确 对待遍历顺序 对象有一套自己既定的规则 在此规则下呢 对象的遍历顺序会受插入元素顺序的影响 但是不完全受插入元素先后顺序的影响 如果您有 必须按插入元素顺序遍历 的场景 可以考虑使用 Map 遍历对象的方法有很多种 我们经常会使用的有 for in 除此之外 还有 Object keysObject entriesObejc getOwnerProP

可能有些同学听过在 JavaScript 中遍历对象顺序不固定的这一说法。事实上,这个说法不是特别准确。

对待遍历顺序,对象有一套自己既定的规则,在此规则下呢,对象的遍历顺序会受插入元素顺序的影响,但是不完全受插入元素先后顺序的影响。如果您有「必须按插入元素顺序遍历」的场景,可以考虑使用 Map

遍历对象的方法有很多种,我们经常会使用的有 for...in ,除此之外,还有:

  1. Object.keys
  2. Object.entries
  3. Obejct.getOwnerProPertyNames
  4. Reflect.ownKeys
  5. ……

上面我们列的几个方法,都按照一样的规则去遍历对象。而实际的遍历规则会根据 key 值类型的不同而不同。

在一个对象中,如果我们的 key 值是像 '1''200'这种正整数格式的字符串。 遍历的顺序是按照 key 值的大小来排列的。

比如我们看这样的一个例子:

const obj = {} obj['10'] = 'a'; obj['9'] = 'b'; obj[8] = 'c'; obj[7] = 'd'; console.log(Object.keys(obj)) //  ["7", "8", "9", "10"] 

我们最后的遍历顺序完全忽视了插入顺序,并且,值得我们注意的是,在对象中,就算我们添加属性时的索引值是 Number 类型,最后的结果还是会被隐式的转为字符串。

数组作为对象的一种,也符合上面的规则,又或许,有上面的表现就是因为要兼容数组的缘故呢。除此之外,通过上面的规则,我们还可以推断出,对类数组(key 值是正整数且有 length 属性)进行遍历也是按照索引顺序的。

另外,如果我们的 key 值是不能转为正整数的字符串,这其中包括了可以转换为负数的字符串( 如 '-1' )、小数格式的字符串(如 '1.0' ) 和其他的字符串。他们的遍历顺序会比较符合直觉,就是插入对象的顺序:

const obj2 = {} obj2['1.1'] = 'a'; obj2['1.0'] = 'b'; obj2['-1'] = 'c'; obj2['jack'] = 'd' console.log(Object.keys(obj2)); //  ["1.1", "1.0", "-1", "jack"] 

事实上,对象的索引值的类型不仅可以是字符串,还可以是 Symbol 类型。对于 Symbol 类型而言,它的遍历顺序也是单纯的按照插入对象的顺序。

如果我们的对象综合了上面所有的情况,即一个对象的索引值出现了所有的类型(各种形式的字符串、Symbol 类型),它会:

  1. 先按照我们上面提的关于正整数的规则遍历正整数部分
  2. 按接下来会插入顺序遍历剩下的字符串
  3. 最后再按照插入顺序遍历 Symbol 类型

相信到这里,大家已经完全明白了对象的遍历顺序问题,最后还有一点值得大家注意的点,是 for...in 的遍历顺序问题。

最开始的时候,for...in 的遍历顺序并没有一个统一的标准,浏览器厂商会按照他们的喜好去设置 for...in 的遍历顺序。如果您对遍历顺序有要求并且要兼容老的浏览器版本,建议不使用它。后来 ES 2019 的 一个提案 对此现象进行了规范,现在 for...in 的顺序也遵循上面的规则。

尽管会遵循上面的规则,但是 for...in 还会遍历原型的属性。所以 for...in 的变量元素的规则是先按照我们上面讲的对象遍历规则去变量对象本身,接下来再按照此规则去遍历对象的原型,以此类推,直到遍历到顶部。

除了最后一个 for...in 的注意点之外,就没有其他的了,其实内容比较少。

这就是遍历对象的全部内容了,谢谢阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/178518.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午5:06
下一篇 2026年3月26日 下午5:07


相关推荐

  • 异步FIFO—Verilog实现

    异步FIFO—Verilog实现本文大部分内容来自 CliffordE Cummings 的 Simulationan amp nbsp FIFODesign 经过自己的一些改变 理论部分为转载 代码自己完成 一 FIFO 简介 FIFO 是英文 FirstInFirst 的缩写 是一种先进先出的数据缓存器 它与普通存储器的区别是没有外部

    2026年3月20日
    3
  • ubuntu安装nginx教程_ubuntu服务器安装教程

    ubuntu安装nginx教程_ubuntu服务器安装教程ubuntu系统安装nginx

    2026年1月27日
    4
  • XML简单介绍

    XML简单介绍

    2021年10月3日
    41
  • js数组排序的几种方法

    js数组排序的几种方法1、冒泡排序以从小到大排序为例,冒泡排序的原理就是通过两层循环把数组中两两相邻的元素进行比较,是的大的元素放到后边,元素交换位置,从而一步步的交换元素的位置,使得最大的元素放到数组的末尾,这样内部的循环就进行了一轮,再根据外部的循环依次再把次大一点的元素放到数组的末尾,从而实现数组的逐步排序。代码如下://冒泡排序vararr=[52,3,8,57,75,2,1];for(…

    2022年4月29日
    92
  • 解决VirtualBox错误:“FATAL:No bootable medium found!”

    解决VirtualBox错误:“FATAL:No bootable medium found!”

    2021年10月28日
    167
  • jQuery EasyUI+ashx实现数据库的CIUD操作

    jQuery EasyUI+ashx实现数据库的CIUD操作对上一个小项目做一个回顾总结,涉及到了jQueryEasyUI+ashx实现数据库的CIUD操作,和大家分享一下。基本思路是用easyui做前端,ashx做后端,中间使用json格式交换数据,其中json主要使用Newtonsoft.Json来序列化和反序列化,为简单起见,后端没有分层,数据都是靠拼接sql,使用一个简单封装的DBHelper来时间数据库的操作。1、数据库表tb_Provid

    2025年6月14日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号