为什么 JS 对象内部属性遍历的顺序乱了

栏目: IT技术 · 发布时间: 4年前

内容简介:需求是要获取一个车型列表,并且输出到页面上按年份排序,故而接口提供的对象简化如下??? 为什么 2013 在前面了,用户肯定希望先看到新的车型的,这不科学!查阅了

问题重现

需求是要获取一个车型列表,并且输出到页面上按年份排序,故而接口提供的对象简化如下

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 对象内部属性遍历的顺序乱了


以上所述就是小编给大家介绍的《为什么 JS 对象内部属性遍历的顺序乱了》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

ggplot2:数据分析与图形艺术

ggplot2:数据分析与图形艺术

哈德利·威克姆 (Hadley Wickham) / 统计之都 / 西安交通大学出版社 / 2013-5-1 / CNY 46.00

中译本序 每当我们看到一个新的软件,第一反应会是:为什么又要发明一个新软件?ggplot2是R世界里相对还比较年轻的一个包,在它之前,官方R已经有自己的基础图形系统(graphics包)和网格图形系统(grid包),并且Deepayan Sarkar也开发了lattice包,看起来R的世界对图形的支持已经足够强大了。那么我们不禁要问,为什么还要发明一套新的系统? 设计理念 打个比......一起来看看 《ggplot2:数据分析与图形艺术》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换