Se eu criar um objeto como este:
var obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";
O objeto resultante sempre será assim?
{ prop1 : "Foo", prop2 : "Bar" }
Ou seja, as propriedades estarão na mesma ordem em que as adicionei?
javascript
object
mellowsoon
fonte
fonte
for-in
,Object.keys
) não tem que apoiá-lo (oficialmente), mas não é a ordem agora. (Não oficialmente: Firefox, Chrome e Edge seguem a ordem especificada, mesmo no for-in e Object.keys, onde eles não são oficialmente obrigados a: jsfiddle.net/arhbn3k2/1 )Respostas:
A ordem de iteração para objetos segue um determinado conjunto de regras desde o ES2015, mas nem sempre segue a ordem de inserção . Simplificando, a ordem de iteração é uma combinação da ordem de inserção para chaves de strings e ordem crescente para chaves semelhantes a números:
Usar uma matriz ou um
Map
objeto pode ser a melhor maneira de conseguir isso.Map
compartilha algumas semelhançasObject
e garante que as chaves sejam iteradas em ordem de inserção , sem exceção:Como uma nota, a ordem das propriedades nos objetos não era garantida antes do ES2015. Definição de um Objeto da ECMAScript Terceira Edição (pdf) :
fonte
SIM (para chaves não inteiras).
A maioria dos navegadores itera as propriedades do objeto como:
Alguns navegadores mais antigos combinam as categorias 1 e 2, repetindo todas as chaves na ordem de inserção. Se suas chaves puderem ser analisadas como números inteiros, é melhor não confiar em nenhuma ordem de iteração específica.
A ordem de inserção das especificações de idioma atual (desde ES2015) é preservada, exceto no caso de chaves que analisam como números inteiros (por exemplo, "7" ou "99"), em que o comportamento varia entre os navegadores. Por exemplo, o Chrome / V8 não respeita a ordem de inserção quando as chaves são analisadas como numéricas.
Especificações de idioma antigo (antes do ES2015) : a ordem da iteração era tecnicamente indefinida, mas todos os principais navegadores estavam em conformidade com o comportamento do ES2015.
Observe que o comportamento do ES2015 foi um bom exemplo de especificação de idioma sendo conduzida pelo comportamento existente, e não o contrário. Para entender melhor essa mentalidade de compatibilidade com versões anteriores, consulte http://code.google.com/p/v8/issues/detail?id=164 , um bug do Chrome que cobre em detalhes as decisões de design por trás do comportamento da ordem de iteração do Chrome . Por um dos comentários (bastante opinativos) sobre esse relatório de bug:
fonte
createFragment
API já conta com isso ... #A ordem das propriedades em objetos normais é um assunto complexo em Javascript.
Enquanto no ES5 explicitamente nenhum pedido foi especificado, o ES2015 tem um pedido em determinados casos. Dado é o seguinte objeto:
Isso resulta na seguinte ordem (em certos casos):
Portanto, existem três segmentos que podem alterar a ordem de inserção (como aconteceu no exemplo). E chaves do tipo inteiro não se atêm à ordem de inserção.
A questão é: para quais métodos esse pedido é garantido nas especificações do ES2015?
Os métodos a seguir garantem a ordem mostrada:
Os seguintes métodos / loops garantem nenhuma ordem:
Conclusão: Mesmo no ES2015, você não deve confiar na ordem das propriedades dos objetos normais em Javascript. É propenso a erros. Use em
Map
vez disso.fonte
No momento da redação deste artigo, a maioria dos navegadores retornava propriedades na mesma ordem em que foram inseridas, mas não era explicitamente garantido o comportamento, portanto, não deveria ser invocado.
A especificação ECMAScript costumava dizer:
No entanto, no ES2015 e posterior, chaves não inteiras serão retornadas em ordem de inserção.
fonte
Toda essa resposta está no contexto de conformidade com as especificações, não no que qualquer mecanismo faz em um momento específico ou historicamente.
Geralmente, não
A questão real é muito vaga.
Em que contexto?
A resposta é: depende de vários fatores. Em geral, não .
Às vezes sim
Aqui é onde você pode contar com a ordem das chaves de propriedade para simples
Objects
:Object.getOwnPropertyNames()
,Reflect.ownKeys()
,Object.getOwnPropertySymbols(O)
Em todos os casos, esses métodos incluem chaves de propriedade não enumeráveis e chaves de pedido, conforme especificado por
[[OwnPropertyKeys]]
(veja abaixo). Eles diferem no tipo de valores-chave que incluem (String
e / ouSymbol
). Nesse contexto,String
inclui valores inteiros.Object.getOwnPropertyNames(O)
Retorna
O
asString
propriedades com chave própria ( nomes de propriedades ).Reflect.ownKeys(O)
Retorna
O
as propriedades própriasString
eSymbol
chave.Object.getOwnPropertySymbols(O)
Retorna
O
asSymbol
propriedades com chave própria .[[OwnPropertyKeys]]
A ordem é essencialmente: tipo inteiro
Strings
na ordem crescente, tipo não inteiroStrings
na ordem de criação, símbolos em ordem de criação. Dependendo de qual função chama isso, alguns desses tipos podem não estar incluídos.O idioma específico é que as chaves são retornadas na seguinte ordem:
Map
Se você estiver interessado em mapas ordenados, considere usar o
Map
tipo introduzido no ES2015 em vez de simplesObjects
.fonte
Nos navegadores modernos, você pode usar a
Map
estrutura de dados em vez de um objeto.Desenvolvedor mozilla> Mapa
fonte
No ES2015, sim, mas não no que você imagina
A ordem das chaves em um objeto não foi garantida até o ES2015. Foi definido pela implementação.
No entanto, no ES2015 em foi especificado. Como muitas coisas no JavaScript, isso foi feito para fins de compatibilidade e geralmente refletia um padrão não oficial existente entre a maioria dos mecanismos JS (com você sabe quem é uma exceção).
A ordem é definida na especificação, na operação abstrata OrdinaryOwnPropertyKeys , que sustenta todos os métodos de iteração nas próprias chaves de um objeto. Parafraseado, a ordem é a seguinte:
Todos índice inteiro teclas (coisas como
"1123"
,"55"
, etc.) em ordem numérica ascendente.Todas as chaves de sequência que não são índices inteiros, em ordem de criação (a mais antiga).
Todas as teclas de símbolo, em ordem de criação (a mais antiga).
É tolice dizer que o pedido não é confiável - é confiável, provavelmente não é o que você deseja, e os navegadores modernos implementam esse pedido corretamente.
Algumas exceções incluem métodos de enumerar chaves herdadas, como o
for .. in
loop. Ofor .. in
loop não garante a ordem de acordo com a especificação.fonte
No ES2015, a ordem das propriedades é garantida para certos métodos que iteram nas propriedades. mas não outros . Infelizmente, os métodos que não garantem um pedido são geralmente os mais usados:
Object.keys
,Object.values
,Object.entries
for..in
rotaçõesJSON.stringify
Porém, a partir do ES2020, a ordem das propriedades desses métodos anteriormente não confiáveis será garantida pela especificação da iteração da mesma maneira determinística que as outras, devido à proposta final : mecânica for-in .
Assim como nos métodos que têm uma ordem de iteração garantida (like
Reflect.ownKeys
eObject.getOwnPropertyNames
), os métodos anteriormente não especificados também irão iterar na seguinte ordem:Isso é o que praticamente toda implementação já faz (e faz há muitos anos), mas a nova proposta a tornou oficial.
Embora a especificação atual deixe para ... na ordem da iteração " quase totalmente não especificada , os mecanismos reais tendem a ser mais consistentes:"
Como toda implementação já itera previsivelmente as propriedades, ela pode ser inserida na especificação sem quebrar a compatibilidade com versões anteriores.
Existem alguns casos estranhos com os quais as implementações atualmente não concordam e, nesses casos, a ordem resultante continuará não especificada. Para que a ordem da propriedade seja garantida :
fonte
Como outros já declararam, você não tem garantia quanto à ordem ao iterar nas propriedades de um objeto. Se você precisar de uma lista ordenada de vários campos, sugeri a criação de uma matriz de objetos.
Dessa forma, você pode usar um loop for regular e ter a ordem de inserção. Você pode usar o método de classificação Array para classificá-lo em uma nova matriz, se necessário.
fonte
Acabei de descobrir isso da maneira mais difícil.
Usando React with Redux, o contêiner de estado cujas chaves eu quero percorrer para gerar filhos é atualizado sempre que a loja é alterada (conforme os conceitos de imutabilidade do Redux).
Assim, para pegar
Object.keys(valueFromStore)
eu useiObject.keys(valueFromStore).sort()
, de modo que pelo menos agora tenho uma ordem alfabética para as teclas.fonte
Do padrão JSON :
(ênfase minha).
Então, não, você não pode garantir o pedido.
fonte