对象 属性 在 javascript 中排序
Object property ordering in javascript
我试图了解 javascript 对象在将它们用作关联数组时有什么用。
来自 ECMA:
4.3.3 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.
在浏览器中使用它们 (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)。
我将这些对象与字符串键一起使用,我真的不希望它们在应用程序的某个阶段更改顺序(如果可能的话),因为它可能会使我正在使用的管道崩溃。
问题是,这种方法对每台 javascript 机器来说是否安全且正常,还是我应该使用其他方法来保证订单永远不会改变?
谢谢!
编辑:
我将它与 node.js 一起使用,它在 V8(chrome 引擎)上运行,'orders non-numerical properties in insertion order'(Felix Kling)。 V8 的这种行为可能会改变吗?
虽然 Chrome 在对象中使用数字作为索引时可以保证 属性 顺序,但 ECMA 规范并没有说 应该 这样做,所以保证我不会依赖这种行为。当您想要保持数据顺序时,我建议您重组数据以使用数组。
我从规范中读到:数组是有序的,对象不是。 Chrome 数字和数字串之间似乎没有区别。 (出于性能原因?)我有时会在需要时避开额外的键数组。
归根结底,是因为V8在代码中处处使用if/else来判断是数组索引还是对象属性而不是两个单独的类来像其他 JS 引擎一样分别处理数组和对象:
https://lastzero.net/2009/09/object-property-ordering-in-google-chrome/
是的,Google 坚持规范,但它也使得将现有数据结构从其他编程语言传递到 JS 变得困难,因为顺序变化出乎意料(甚至 John Resig 都感到惊讶!)。所以你必须使用不同的(可能更慢的)数据结构或使用转换器,这使得代码更复杂。
这取决于代码 运行 所在的环境,以及用于迭代键的方法。
在 ES5 及更早版本中,无论使用何种方法,都没有定义顺序。
在 ES6+ 中, 遍历键(但不是全部)保证按顺序遍历:
(1)递增数字键(如0
、1
、2
),后面是
(2) 非数字键按插入顺序,后跟
(3) 个符号按插入顺序排列。
保证以这种方式运行的方法包括:
Reflect.ownKeys
Object.getOwnPropertyNames
Object.getOwnPropertySymbols
Object.defineProperties
- 对象rest/spread
这些都是调用内部方法[[OwnPropertyKeys]]
,保证顺序
不保证以任何顺序迭代的方法,即使在 ES6+ 环境中,包括:
for..in
Object.keys
、Object.values
、Object.entries
JSON.stringify
这些方法都调用了EnumerateObjectProperties,其中明确指出:
The mechanics and order of enumerating the properties is not specified
综上所述,尽管不能保证顺序,但在较新的环境中,上述方法几乎总是以与 Reflect.ownKeys
相同的确定顺序迭代。也许你不应该依赖它,但它可能会起作用,至少现在是这样。
如果你想要一个
method to guarantee that order won't ever change?
然后要可靠地迭代一个对象,您应该使用 Reflect.ownKeys
或 Object.getOwnPropertyNames
.
进行迭代
May this behaviour of V8 change?
如果您使用保证以特定顺序迭代的方法之一,行为将不会改变,因为 Javascript 几乎始终保持向后兼容性,现在所需的顺序已在规范,未来的任何更改都不会更改该顺序。
我试图了解 javascript 对象在将它们用作关联数组时有什么用。
来自 ECMA:
4.3.3 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.
在浏览器中使用它们 (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)。
我将这些对象与字符串键一起使用,我真的不希望它们在应用程序的某个阶段更改顺序(如果可能的话),因为它可能会使我正在使用的管道崩溃。
问题是,这种方法对每台 javascript 机器来说是否安全且正常,还是我应该使用其他方法来保证订单永远不会改变?
谢谢!
编辑: 我将它与 node.js 一起使用,它在 V8(chrome 引擎)上运行,'orders non-numerical properties in insertion order'(Felix Kling)。 V8 的这种行为可能会改变吗?
虽然 Chrome 在对象中使用数字作为索引时可以保证 属性 顺序,但 ECMA 规范并没有说 应该 这样做,所以保证我不会依赖这种行为。当您想要保持数据顺序时,我建议您重组数据以使用数组。
我从规范中读到:数组是有序的,对象不是。 Chrome 数字和数字串之间似乎没有区别。 (出于性能原因?)我有时会在需要时避开额外的键数组。
归根结底,是因为V8在代码中处处使用if/else来判断是数组索引还是对象属性而不是两个单独的类来像其他 JS 引擎一样分别处理数组和对象:
https://lastzero.net/2009/09/object-property-ordering-in-google-chrome/
是的,Google 坚持规范,但它也使得将现有数据结构从其他编程语言传递到 JS 变得困难,因为顺序变化出乎意料(甚至 John Resig 都感到惊讶!)。所以你必须使用不同的(可能更慢的)数据结构或使用转换器,这使得代码更复杂。
这取决于代码 运行 所在的环境,以及用于迭代键的方法。
在 ES5 及更早版本中,无论使用何种方法,都没有定义顺序。
在 ES6+ 中,
(1)递增数字键(如0
、1
、2
),后面是
(2) 非数字键按插入顺序,后跟
(3) 个符号按插入顺序排列。
保证以这种方式运行的方法包括:
Reflect.ownKeys
Object.getOwnPropertyNames
Object.getOwnPropertySymbols
Object.defineProperties
- 对象rest/spread
这些都是调用内部方法[[OwnPropertyKeys]]
,保证顺序
不保证以任何顺序迭代的方法,即使在 ES6+ 环境中,包括:
for..in
Object.keys
、Object.values
、Object.entries
JSON.stringify
这些方法都调用了EnumerateObjectProperties,其中明确指出:
The mechanics and order of enumerating the properties is not specified
综上所述,尽管不能保证顺序,但在较新的环境中,上述方法几乎总是以与 Reflect.ownKeys
相同的确定顺序迭代。也许你不应该依赖它,但它可能会起作用,至少现在是这样。
如果你想要一个
method to guarantee that order won't ever change?
然后要可靠地迭代一个对象,您应该使用 Reflect.ownKeys
或 Object.getOwnPropertyNames
.
May this behaviour of V8 change?
如果您使用保证以特定顺序迭代的方法之一,行为将不会改变,因为 Javascript 几乎始终保持向后兼容性,现在所需的顺序已在规范,未来的任何更改都不会更改该顺序。