js中关于for...in遍历对象属性的顺序问题

时间: 2018-02-27阅读: 833标签: 对象

下面是一个对象,并为对象添加了一些属性:

var obj = {
      city: "Beijing",
      12: 12,
      7: 7,
      0: 0,
      "-2": -2,
      "age": 15,
      "-3.5": -3.5,
      7.7: 7.7,
      _: "___",
      online: true,
      3: 3,
      "23": "23",
      "44": 44
}

对象使用obj.length时,它得到的值是undefined的,所以只能通过for...in循环获取对象的属性:

for(let key in obj){
  console.log(key);
}

我们发现并没有按属性的顺序显示,而且顺序在各个浏览器下显示也不同。 这是为什么呢?


标准参考

根据 ECMA-262(ECMAScript)第三版中描述,for-in 语句的属性遍历的顺序是由对象定义时属性的书写顺序决定的

在现有最新的 ECMA-262(ECMAScript)第五版规范中,对 for-in 语句的遍历机制又做了调整,属性遍历的顺序是没有被规定的

新版本中的属性遍历顺序说明与早期版本不同,这将导致遵循 ECMA-262 第三版规范内容实现的 JavaScript 解析引擎在处理 for-in 语句时,与遵循第五版规范实现的解析引擎,对属性的遍历顺序存在不一致的问题。


Chrome Opera 中使用 for-in 语句遍历对象属性时会遵循一个规律,它们会先提取所有 key 的 parseFloat 值为非负整数的属性, 然后根据数字顺序对属性排序首先遍历出来,然后按照对象定义的顺序遍历余下的所有属性。其它浏览器则完全按照对象定义的顺序遍历属性。

以上代码测试了对象属性 key 为正负整数及小数、字符串和符号的情况下 for-in 语句遍历的顺序。执行代码,各浏览器中表现如下: 


Chrome OperaIE6 IE7 IE8 Firefox Safari
result in Chrome and Operaresult in other browsers

经测试该问题与文档模式、属性 value 的数据类型以及对象是否是直接量创建的无关。

可见,Chrome Opera 的 JavaScript 解析引擎遵循的是新版 ECMA-262 第五版规范。因此,使用 for-in 语句遍历对象属性时遍历书序并非属性构建顺序。而 IE6 IE7 IE8 Firefox Safari 的 JavaScript 解析引擎遵循的是较老的 ECMA-262 第三版规范,属性遍历顺序由属性构建的顺序决定。

【注】:IE6 IE7 IE8 Firefox Safari 浏览器的 JavaScript 解析引擎完成时间早于 ECMA-262 第五版规范发布时间,他们均遵守第三版规范,这无可厚非。


解决方案

for-in 语句无法保证遍历顺序,应尽量避免编写依赖对象属性顺序的代码。如果想顺序遍历一组数据,请使用数组并使用 for 语句遍历。 如果想按照定义的次序遍历对象属性,请参考本文针对各浏览器编写特殊代码。


参考 http://www.w3help.org/zh-cn/causes/SJ9011  

 

秒懂JS对象、构造器函数和原型对象之间的关系

学习JS的过程中,想要掌握面向对象的程序设计风格,对象模型(原型和继承)是其中的重点和难点,拜读了各类经典书籍和各位前辈的技术文章,感觉都太过高深,花费了不少时间才搞明白

js中Object.create vs new Function() 的区别

之前学习JavaScript 权威指南,说以后在JavaScript建立对象请使用Object.create() 尽量少使用 new Function() .这两个新建对象的方法到底有什么不同呢?new 方式实现方式,实际上是先新建了一个Object对象,再用这个对象继承至Base,最后再绑定this.

js中new的本质

用 var anObject = new aFunction() 形式创建对象的过程实际上可以分为三步: 第一步是建立一个新对象; 第二步将该对象内置的原型对象设置为构造函数prototype引用的那个原型对象; 第三步就是将该对象作为this参数调用构造函数,完成成员设置等初始化工作。

javascript Es5面向对象和 Es6面向对象

javascript es6之前的面向对象方法:一般使用构造函数来实现。通过ES6的class 类来创建结果和上面用构造函数创建的是一样的;当然里面也可以写方法 function;用构造函数本身 直接点 ▪ 上的 属性或者 function() 函数 叫静态属性或方法; 一般不会这样做;

js之global 全局对象 方法

global 作为js的全局对象,但其是无法直接访问的,但是在浏览器中浏览器是将这个对象当做是window对象的一部分,即Date 等Global的属性使用window.Date 可访问到

js中arguments对象_理解arguments参数

在js中万物皆对象,甚至数组字符串函数都是对象。所以这个叫做arguments的东西也是个对象,而且是一个特殊的对象,它的属性名是按照传入参数的序列来的,第1个参数的属性名是0,第2个参数的属性名是1,以此类推,并且它还有length属性,

Javascript的对象拷贝

Javascript中对象拷贝的多种方式,以及探究一下深拷贝和浅拷贝。在开始之前,我先提一下一些基础知识:Javascript 的对象只是指向内存中某个位置的指针。这些指针是可变的,也就是说,它们可以重新被赋值。因此,单单复制这个指针的结果是,有两个指针指向内存中的同一块地址。

js基础_究竟什么是变量对象,什么是活动对象?

在写程序的时候会定义很多变量和函数,那js解析器是如何找到这些变量和函数的?变量对象是与执行上下文对应的概念,在执行上下文的创建阶段,它依次存储着在上下文中定义的以下内容:函数的所有形参、所有函数声明、所有变量声明

js包装对象

对象是 JavaScript 语言最主要的数据类型,三种原始类型的值——数值、字符串、布尔值——在一定条件下,也会自动转为对象,也就是原始类型的包装对象。所谓包装对象,就是分别与数值、字符串、布尔值相对应的Number、String、Boolean三个原生对象。

location.hash属性#_window.location.hash 使用

hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分),#是用来指导浏览器动作的,都会被浏览器解读为位置标识符 , 这意味着这些字符都不会被发送到服务器端。对服务器端完全无用。所以,HTTP请求中不包括#。

fly63.com版权所有,内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权,请与小编联系!情况属实本人将予以删除!