我可以假设Object.keys的响应顺序相同吗?

时间:2014-02-20 09:02:55

标签: javascript

{"/book":1,"/order":2,"deliver":3}

在我的应用程序的用户界面中,当我点击/预订时,我知道从地图上可以找到什么步骤。  有时我只想通过递增数字来进入下一步,但确保URL也会发生变化。

如何从一步到另一键进行反向映射。

我遇到了ECMAScript 5中介绍的Object.keys。 返回的键列表中的元素顺序是否始终相同?

["/book","/order","deliver"] 

如果是,那为什么呢?字典是无序的吗?

2 个答案:

答案 0 :(得分:1)

由实施决定。来自ES5 spec on Object.keys

  

如果实现为for-in语句定义了特定的枚举顺序,则必须在此算法的步骤5中使用相同的枚举顺序。

那里提到的“第5步”没有指定订单:

  

5.对于O的每个自己的可枚举属性,其名称为String ...

答案 1 :(得分:1)

ECMAScript 5.1 specification表示

  

当使用参数O调用keys函数时,执行以下步骤   采取:

     
      
  1. 如果Type(O)不是Object,则抛出TypeError异常。
  2.   
  3. 设n为O
  4. 的自身可枚举属性的数量   
  5. 让数组成为创建新Object的结果,就好像通过表达式new Array(n),其中Array是标准内置   具有该名称的构造函数。
  6.   
  7. 让索引为0。
  8.   
  9. 对于名称String为P的O的每个自己的可枚举属性:      (a)使用参数ToString(index)调用数组的[[DefineOwnProperty]]内部方法,PropertyDescriptor {[[Value]]:P,   [[Writable]]:true,[[Enumerable]]:true,[[Configurable]]:true},和   假。      (b)增加指数1。
  10.   
  11. 返回阵列。
  12.         

    如果实现定义了枚举的特定顺序   for-in语句,必须在步骤5中使用相同的枚举顺序   这个算法。

Mozilla开发网络可以说明for-in loop

  

for ... in循环以任意顺序迭代对象的属性(有关为什么不能依赖于迭代的看似有序性的原因,请参阅delete运算符,至少在跨浏览器设置中)。

delete operator的引用导致了这一点:

  

虽然ECMAScript使对象的迭代顺序依赖于实现,但似乎所有主流浏览器都支持基于最先添加的属性的迭代顺序(至少对于不在原型上的属性)。但是,对于Internet Explorer,当在属性上使用delete时,会导致一些令人困惑的行为,从而阻止其他浏览器将对象文字等简单对象用作有序关联数组。在资源管理器中,虽然属性值确实设置为未定义,但如果后来添加了一个具有相同名称的属性,则该属性将在其旧位置迭代 - 而不是在迭代序列的末尾,正如人们可能期望的那样删除了该属性,然后将其添加回来。

     

因此,如果要在跨浏览器环境中模拟有序关联数组,则必须使用两个单独的数组(一个用于键,另一个用于值),或者构建一个单属性数组对象等。

我认为从中得出的结论是,在单个浏览器中,订单将是任意的但是一致但如果您比较多个浏览器,那么这些浏览器的顺序可能会有所不同(特别是如果您要删除并重新添加属性)。

修改

如果您想根据相关值对键进行排序,那么您可以执行以下操作:

var map = { b: 2, a: 1, c: 3 };

var keys = Object.keys( map );

console.log( keys ); // [ 'b', 'a', 'c' ]

var sorted_keys = keys.slice(0); // sliced so that we can see the difference in order

sorted_keys.sort( function( a, b ){ return map[a] - map[b]; } );

console.log( sorted_keys ); // [ 'a', 'b', 'c' ]