我试图了解javascript对象在使用它们作为关联数组时的作用。
来自ECMA:
4.3.3对象是Object类型的成员。它是无序属性集合,每个属性都包含一个基元 价值,对象或功能。存储在属性中的函数 对象称为方法。
在浏览器中使用它们(chrome):
x = { 2: 'a', 3: 'b', 1: 'c' }
> Object {1: "c", 2: "a", 3: "b"}
y = { 'b': 2, 'c': 3, 'a': 1 }
> Object {b: 2, c: 3, a: 1}
虽然在第一个以数字作为键的例子中,它们变得有序,但在第二个带有字符串的例子中,它们赢了(订购= a,b,c)。
我正在使用带有字符串键的这些对象,我真的不希望它们在应用程序的某个阶段(如果可能的话)改变顺序,因为它可能会使我正在使用的管道崩溃。 / p>
问题是,这种方法对于每台javascript机器都安全且正常,还是应该使用其他方法来保证订单不会发生变化?
谢谢!
编辑: 我在node.js上使用它,它运行在V8(chrome引擎)上,它按照插入顺序排序非数字属性(Felix Kling)。愿V8的这种行为改变吗?
答案 0 :(得分:5)
虽然Chrome可以在使用数字作为对象中的索引时保证属性顺序,但ECMA规范并没有说它应该这样做,所以保证我不会依赖这种行为。我建议您在需要保持数据顺序时重组数据以使用数组。
答案 1 :(得分:1)
在一天结束时,它是因为V8在代码中使用if / else来确定它是数组索引还是对象属性而不是两个单独的类来处理数组和对象与其他JS引擎分开:
https://lastzero.net/2009/09/object-property-ordering-in-google-chrome/
是的,谷歌坚持这些规格,但它也很难将现有的数据结构从其他编程语言传递给JS,因为订单意外地改变了(甚至John Resig也很惊讶!)。因此,您必须使用不同的(可能更慢的)数据结构或使用转换器,这会使代码更复杂。
答案 2 :(得分:0)
我从规范中读到:数组是有序的,对象不是。 Chrome似乎在数字和数字字符串之间没有区别。 (出于性能原因?)我有时会在需要时回避额外的一系列键。
答案 3 :(得分:0)
这取决于运行代码的环境以及用于迭代键的方法。
在ES5和更早版本中,无论使用哪种方法,都没有定义的顺序。
在ES6 +中,保证对键(但不是全部)进行迭代的some methods可以按顺序进行迭代:
(1)依次增加数字键(例如0
,1
,2
),然后是
(2个)非数字键,按插入顺序,后跟
(3)个符号按插入顺序。
可以保证以这种方式运行的方法包括:
Reflect.ownKeys
Object.getOwnPropertyNames
Object.getOwnPropertySymbols
Object.defineProperties
所有这些都调用内部方法[[OwnPropertyKeys]]
,以保证顺序。
即使在ES6 +环境中,也不能保证 以任何顺序进行迭代的方法包括:
for..in
Object.keys
,Object.values
,Object.entries
JSON.stringify
这些方法都调用EnumerateObjectProperties,该方法明确指出:
未指定枚举属性的机制和顺序
所有这些,即使不能保证顺序,在较新的环境中,上述方法几乎总是以与Reflect.ownKeys
相同的确定性顺序进行迭代。也许您不应该依赖它,但是它可能会起作用,至少目前是这样。
如果您想要
保证订单永远不会改变的方法?
然后要可靠地遍历对象,则应使用Reflect.ownKeys
或Object.getOwnPropertyNames
进行遍历。
V8的这种行为会改变吗?
如果您使用保证以特定顺序进行迭代的方法之一,则行为不会改变,因为Javascript几乎始终保持向后兼容性,并且由于规范中已描述了所需的顺序,因此以后将不再更改更改顺序。