为什么 JS 对象内部属性遍历的顺序乱了
问题重现
需求是要获取一个车型列表,并且输出到页面上按年份排序,故而接口提供的对象简化如下
let obj = { '2018': {modelCode: "204313",modelName: "2018款 Vanquish 6.0L S Coupe"},'2017': {modelCode: "202479",modelName: "2017款 Rapide 6.0L AMR"},'2013': {modelCode: "139705",modelName: "2013款 Rapide 6.0L S"}
}console.log(obj)
// {2013: {…}, 2017: {…}, 2018: {…}}
??? 为什么 2013 在前面了,用户肯定希望先看到新的车型的,这不科学!
解释
查阅了 ECMA-262 3rd edition ,如下文 It is an unordered collection of properties 就说到 ES3 标准的对象不排序,插入是啥顺序,遍历就是啥顺序
An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method.
而我查阅了 ECMA-262 5.1 edition ,如下文,读者们应该留意到了少了 unordered collection 的描述。并且之后的 ES 版本对对象的描述都是如此。
an object is a member of the remaining built-in type Object; and a function is a callable object. A function that is associated with an object via a property is a method.
故此,我能得出结论 Chrome 等新版浏览器 js 引擎遵循的是新版 ECMA-262 5th。因此,使用 for-in 语句遍历对象属性时遍历书序并非属性构建顺序。而 IE6、7、8 等旧版本浏览器的 js 解析引擎遵循的是较老的 ECMA-262 3rd,属性遍历顺序由属性构建的顺序决定。
故此 Chrome 的 js 引擎遍历对象属性时会遵循一个规律:
它们会先提取所有 key 的 parseFloat 值为非负整数的属性,然后根据数字顺序对属性排序首先遍历出来,然后按照对象定义的顺序遍历余下的所有属性。
猜想
按照上面的解释,那么我来一个例子
let obj = { 'b': 'testb','a': 'testa','1': 'test1','测': 'test测','2': 'test2'
}console.log(Object.keys(obj));// [1, 2, 'b', 'a', '测']
果然会把 '1' 和 '2' 这种能被 parseFloat 转化为正整数的提到前面并且按照升序排
而 'a' 和 '测' 没法转为整数那就排在 '1'、'2' 后并按照构建时的顺序拍
解决问题
回到问题,对象既然不能保证其顺序,那么使用数组来进行遍历吧。
当然业务中如果需要查某个年份的车型,而不想要每次都遍历一遍的来找的话。可以维护两份数据。一份数组,用于遍历输出,一份对象,用于查。
补充
直到最近在极客时间翻阅到李兵老师的 图解 Google V8 的第三节 "V8采用了哪些策略提升了对象属性的访问速度?" 时,我终于发现了更深层次的解释。
借下图说法:V8 里的对象其实维护两个属性,会把数字放入线性的 elements 属性中,并按照顺序存放。会把非数字的属性放入 properties 中,不会排序,顺便说一句它可能是线性结构,取决于属性数量的多少。寻找属性时先 elements 而后在 properties。
为什么 JS 对象内部属性遍历的顺序乱了相关推荐
- 遍历和添加json对象的属性 和 遍历普通js对象的属性
1. 遍历 json 对象的属性 //定义json对象 var person= { name: 'zhangsan', pass: '123', fn: function(){ alert(this. ...
- 使用变量的值作为JS对象的属性名,从而获取其对应的值
使用变量的值作为JS对象的属性名,从而获取其对应的值 <script>var object={"a":1111,"b":2222};var para ...
- 基于js对象,操作属性、方法详解
一,概述 在Java语言中,我们可以定义自己的类,并根据这些类创建对象来使用,在Javascript中,我们也可以定义自己的类,例如定义User类.Hashtable类等等. 目前在Javascrip ...
- JS对象 - Array属性方法汇总
属性名 描述 prototype 为对象添加属性.方法 constructor 返回数组对象引用 length 返回数组元素数目 方法名 描述 返回 更改原数组 concat() 连接多个数组 连接后 ...
- python魔法属性_查看对象内部属性的名称和值,Python“魔法”属性__dict__的使用...
我们知道,Python中"一切皆对象",Python是一门真正意义上面向对象的编程语言.因此,如果对对象内部存储结构了解不深入,在学习Python的道路上是没有办法进阶的.今天,我 ...
- php 获取js对象的属性值,js获取对象,数组所有属性键值(key)和对应值(value)的方法示例...
本文实例讲述了js获取对象,数组所有属性键值(key)和对应值(value)的方法.分享给大家供大家参考,具体如下: var values=function(object) { var values ...
- JS对象的属性名规则
/* * 使用对象字面量,可以在创建对象时,直接指定对象中的属性 * 语法:{属性名:属性值,属性名:属性值-} * 对象字面量的属性名可以加引号也可以不加,建议不加, * 如果要使用一些特殊的名字, ...
- 给JS对象添加属性和方法
方式一:在定义对象时,直接添加属性和方法 function Person(name,age) {this.name = name;this.age = age;this.say = function( ...
- Js 对象添加属性
var arr = new Array(); arr[0] = jQuery("#data1").val(); var obj = {}; obj.y='abc'; arr.pus ...
最新文章
- C++知识点53——虚继承
- Linux Malloc分析-从用户空间到内核空间
- Android之build.gradle配置签名
- 最强鸿蒙系统txt_鸿蒙系统升级时间确认,哪些手机有望成为首批“宠儿”?
- CSS之media Query
- 【转】VTK与Qt整合的示例
- 【LeetCode笔记】48. 旋转图像(Java、矩阵、偏数学、原地算法)
- 补码到底是个什么东西
- java基础知识回顾之---java String final类普通方法的应用之“按照字节截取字符串”...
- 摄像机标定之四大坐标系之间转换关系详解
- STM32 串口程序下载
- 项目管理师证怎么考?报考条件有哪些?
- 2020中南大学计算机学院考研初试成绩,中南大学2020考研复试分数线已公布
- Modbus设备通过边缘网关接入阿里云IoT平台
- 威纶通屏,标准程序范本非常漂亮都是重新做的素材,可以省去很多时间就能做出好看的界面
- Nexus私服(三)
- 电信4g网络问题及恢复方案
- Element快速入门
- 淘宝天猫如何导入数据包批量上传宝贝的方法
- MySQL读已提交有间隙锁吗_mysql中的幻读与间隙锁
热门文章
- Compose 实现手写春联效果
- Python中self用法详解
- Kafka创建Topic的两种方式
- 【数学】SSL_1335 蛋糕切割
- vue-2.5.16.js:597 [Vue warn]: Unknown custom element: ocean - did you register the component corre
- 新浪微博桌面客户端 v3.0.5.35466 官方PC版
- DataToExcel
- QQ在线代码,MSN在线代码,雅虎通在线代码,阿里旺旺在线代码
- PHP getimagesize(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL rou
- 【ppt制作软件】Focusky教程 | 怎样实现表格的行列转换?