Necesito recorrer un objeto JavaScript tratándolo como una matriz con claves personalizadas. Sé que esto no es totalmente compatible, ya que las propiedades no tienen un orden intrínseco, pero dado que siempre vuelvo a ordenar las propiedades, encontré este enfoque simple y confiable ... hasta ahora.
El problema ocurre cuando las teclas son números o cadenas que se pueden convertir como números.
Cuando ejecuto este código:
var test1 = {4294966222:"A",4294966333:"A",4294966111:"A"};
var test2 = {4294968222:"A",4294968333:"A",4294968111:"A"};
for (var k in test1) {console.log(k);}
console.log("---");
for (var k in test2) {console.log(k);}
la salida es:
4294966111
4294966222
4294966333
---
4294968222
4294968333
4294968111
Lo que significa:
- (prueba1) si las teclas están por debajo de 2 ^ 32 (4,294,967,296), se reordenan automáticamente, la más pequeña primero
- (test2) si las claves están por encima de 2 ^ 32, NO se reordenan.
La pregunta es: ¿por qué está sucediendo esto?
Dado que todos los navegadores que probé (Google Chrome 79.0, Mozilla Firefox 71.0, Microsoft Edge 44.18362, Internet Explorer 11.535) están de acuerdo con esta salida, debe haber alguna especificación oficial.
Actualizar
Probé muchos números antes de descubrir que era una cuestión de umbral. Encontré extraño que la secuencia 2,3,1 se comporte de manera diferente a tres marcas de tiempo ordenadas de la misma manera.
fuente
test1
ytest2
. Creo que el "problema" proviene del almacenamiento en caché de claves en la implementación V8 de la especificación.4294968333
y4294968111
son mayores que2 ** 32
(que es4294967296
). Por lo tanto, no son indicadores de matriz, por lo que se repiten en orden de creación de propiedad, en lugar de en orden numérico ascendente, que es exactamente lo que están haciendo en el violín, como se esperaba. (ver mi respuesta)Respuestas:
Esto es de esperarse. Según la especificación , el método que itera sobre las propiedades
OrdinaryOwnPropertyKeys
, hace:El orden numérico ascendente solo se aplica a las propiedades que son indicadores de matriz.
Entonces, ¿qué es un "índice de matriz"? Búscalo :
Por lo tanto, las propiedades numéricas que son mayores que 2 ^ 32 no son indicadores de matriz y, por lo tanto, se repiten en orden de creación de propiedades. Sin embargo, las propiedades numéricas que son menores que
2^32
las de una matriz y se repiten en orden numérico ascendente.Así por ejemplo:
1
: Índice de matriz, se repetirá numéricamente10
: Índice de matriz, se repetirá numéricamente4294968111
: Mayor que2 ** 32
, se repetirá una vez que finalicen las indicaciones de la matriz, en orden de creación de propiedades9999999999999
: Mayor que2 ** 32
, se repetirá una vez que finalicen las indicaciones de la matriz, en orden de creación de propiedadesAdemás, tenga en cuenta que, contrariamente a la creencia popular, el orden de iteración de la propiedad también está garantizado por la especificación, gracias a la propuesta de iteración for-in que es la etapa 4.
fuente
Esto tiene que ver con la forma en que se atraviesan las teclas de un objeto.
De acuerdo con las especificaciones ES6, debería ser:
http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
Eso significa que si el valor de una clave permanece igual si se convierte en un número de 53 bits sin signo y se trata como un índice entero que se ordena en orden numérico ascendente.
Si esto falla, se trata como una clave de cadena, que se ordena de la forma en que se agregaron al objeto.
El problema aquí es que todos los principales navegadores aún no siguen esta especificación y en su lugar utilizan un índice de matriz que se limita a un número positivo hasta . Entonces, cualquier cosa por encima de ese límite es una clave de cadena en realidad.
fuente