Eu preciso percorrer um objeto JavaScript tratando-o como uma matriz com chaves personalizadas. Eu sei que isso não é totalmente suportado, já que as propriedades não têm ordem instrínseca, mas como eu sempre reorganizo as propriedades, achei essa abordagem simples e confiável ... até agora.
O problema ocorre quando as teclas são números ou cadeias que podem ser convertidas como números.
Quando executo esse 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);}
a saída é:
4294966111
4294966222
4294966333
---
4294968222
4294968333
4294968111
Que significa:
- (test1) se as chaves estiverem abaixo de 2 ^ 32 (4.294.967.296), elas serão reordenadas automaticamente, a menor primeira
- (test2) se as chaves estiverem acima de 2 ^ 32, elas NÃO serão reordenadas.
A questão é: por que isso está acontecendo?
Como todos os navegadores que testei (Google Chrome 79.0, Mozilla Firefox 71.0, Microsoft Edge 44.18362, Internet Explorer 11.535) concordam com essa saída, deve haver alguma especificação oficial.
Atualizar
Testei muitos números antes de descobrir que era uma questão de limiar. Achei estranho que a sequência 2,3,1 se comporte de maneira diferente de três registros de data e hora ordenados da mesma maneira.
fonte
test1
etest2
. Eu acho que o "problema" é do cache de chaves na implementação da especificação V8.4294968333
e4294968111
são maiores que2 ** 32
(o que é4294967296
). Portanto, eles não são indicações de matriz, portanto são iterados em ordem de criação de propriedade, em vez de em ordem numérica crescente - que é exatamente o que eles estão fazendo no violino, como esperado. (veja minha resposta)Respostas:
Isso é esperado. De acordo com a especificação , o método que itera sobre as propriedades
OrdinaryOwnPropertyKeys
:A ordem numérica crescente aplica-se apenas às propriedades que são indicações de matriz.
Então, o que é um "índice de matriz"? Procure ::
Portanto, propriedades numéricas maiores que 2 ^ 32 não são indicações de matriz e, portanto, iteraram na ordem de criação da propriedade. No entanto, propriedades numéricas menores que
2^32
são indicativas de matriz e são iteradas em ordem numérica crescente.Então, por exemplo:
1
: O índice da matriz será iterado numericamente10
: O índice da matriz será iterado numericamente4294968111
: Maior que2 ** 32
, será iterado após a conclusão das indicações da matriz, na ordem de criação da propriedade9999999999999
: Maior que2 ** 32
, será iterado após a conclusão das indicações da matriz, na ordem de criação da propriedadeAlém disso, lembre-se de que, contrariamente à crença popular, a ordem de iteração de propriedade também é garantida pela especificação, graças à proposta de iteração integrada, que é o estágio 4.
fonte
Isso tem a ver com a maneira como as chaves de um objeto são percorridas.
De acordo com as especificações ES6, deve ser:
http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
Isso significa que se o valor de uma chave permanecer o mesmo se convertido em um número de 53 bits não assinado e vice-versa, ele será tratado como um índice inteiro que é classificado em ordem numérica crescente.
Se isso falhar, é tratado como uma chave de cadeia, ordenada da maneira que foi adicionada ao objeto.
O problema aqui é que todos os principais navegadores ainda não seguem essa especificação e usam um índice de matriz, que é limitado a um número positivo de até . Portanto, qualquer coisa acima desse limite é realmente uma chave de cadeia.
fonte