对象内的属性列表是无序的!
首先清楚一点,JS世界中(其他语言不了解)对象是一个包含各种“特性”的单一实体,它所包含的“特性”(属性)是键、值对形式的组合,本身是无序的,对象中属性书写时的排列顺序不会影响对象属性的获取。比如下面这个对象:
var object={c:3, b:2, a:1, d:4};
开发者通过声明属性名(键名)作为索引(object[a]===1
、object.b===2
)取到对应的属性值。
对象就是对象,一个包含各种特性(属性/方法)的单一实体,而数组是诸多单一实体的集合,这个集合拥有着序列化的特性。
var array1=['a','b','c','d'];
var array2=[
{id:1, name:'Jack', age:32, gender:'male'},
{id:2, name:'Mary', age:28, gender:'female'},
{id:3, name:'Tom', age:18, gender:'male'},
...
];
序列的排序是有意义的,对一个序列做倒序、顺序的排列是极其普遍的应用。数组用有序的数字作为索引,并用以获取对应序位的值(array1[0]==='a'
、array2[2].id===3
)。
Console 上的奇怪现象
之所以要强调“对象内的元素是无序的”这个要点,是为了突出这个问题或者怪象。我们用Chrome浏览器的调试工具做演示,来运行一段代码看看:
console.log({3:3, 2:2, 1:1, 4:4});
输出:{1: 1, 2: 2, 3: 3, 4: 4}
!奇怪吗?结果按照数字键名的大小被重新排序输出了。那我们把键名换成字母是不是会按照字母顺序排序呢:
console.log({c:3, b:2, a:1, d:4});
输出:{c:3, b:2, a:1, d:4}
,并没有排序!
我终究还是清楚 Chrome 浏览器是优于 IE 之流的,于是试着打开IE的调试窗口来看看:
我们发现在 IE 里,以字母作为键名的对象内容也被按照字母顺位排序输出了!会不会是不同浏览器解析方式不同所至?要是这样的话 node.js 用了和 Chrome 相同的解析器 v8,那么 node.js 的输出结果应该是一样的:
果然!再试试 Firefox:
结果和 Chrome 一样。
为什么?
我们发现各浏览器的调试工具都对以数字作为键名的对象内容做了排序,而只有 IE 同时还对属性名做了排序,这样做的目的难道只是为开发者便于阅读而带来的体验优化,还是因为不同于 Chrome、Firefox 的内核所致?
如果只是开发时的阅读体验,显然不太先进的 IE 做得更加全面,但是我们要知道,作为对象,主动排序是无意义的,除非特定要求需要把对象内容做文本序列化输出。
这里有个相关问题的讨论帖:http://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order