Qual é a maneira mais rápida de contar o número de chaves / propriedades de um objeto? É possível fazer isso sem iterar sobre o objeto? ou seja, sem fazer
var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;
(O Firefox forneceu uma __count__
propriedade mágica , mas isso foi removido em algum momento da versão 4.)
Respostas:
Para fazer isso em qualquer ambiente compatível com ES5 , como Nó , Chrome, IE 9+, Firefox 4+ ou Safari 5+:
fonte
Você pode usar este código:
Em seguida, você também pode usar isso em navegadores antigos:
fonte
(Object.prototype.hasOwnProperty.call(obj, k))
?hasOwnProperty
é necessária. Ele retorna apenas propriedades definidas no próprio objeto.obj.hasOwnProperty(k)
(eu realmente fiz isso no meu post original, mas atualizei mais tarde).hasOwnProperty
está disponível em todos os objetos porque faz parte doObject
protótipo do, mas no raro caso de esse método ser removido ou substituído, você poderá obter resultados inesperados. Ao chamá-Object.prototype
lo, torna-o um pouco mais robusto. A razão para usarcall
é porque você deseja chamar o método emobj
vez de no protótipo.Se você estiver usando o Underscore.js, poderá usar o _.size (obrigado @douwe):
_.size(obj)
Como alternativa, você também pode usar _.keys, o que pode ser mais claro para alguns:
_.keys(obj).length
Eu recomendo o Underscore, é uma biblioteca restrita para fazer muitas coisas básicas. Sempre que possível, eles correspondem ao ECMA5 e adiam para a implementação nativa.
Caso contrário, eu apoio a resposta da @ Avi. Editei-o para adicionar um link ao documento MDC, que inclui o método keys () que você pode adicionar a navegadores não-ECMA5.
fonte
_.keys(obj).length
funcionou melhor para mim, porque meu objeto de retorno às vezes é uma string simples sem propriedades dentro dele._.size(obj)
dá-me o comprimento da corda, enquanto_.keys(obj).length
retorna 0.Object.keys
internamente. O sublinhado também copia todas as chaves em uma matriz dentro de umfor..in
loop, seObject.keys
não estiver definido.A implementação padrão de Objeto ( Propriedades e Métodos Internos do Objeto ES5.1 ) não exige que um
Object
rastreie seu número de chaves / propriedades; portanto, não deve haver uma maneira padrão de determinar o tamanho de um objeto.Object
sem iterar explícita ou implicitamente suas chaves.Então, aqui estão as alternativas mais usadas:
1. Object.keys do ECMAScript ()
Object.keys(obj).length;
Trabalha iterando internamente as chaves para calcular uma matriz temporária e retorna seu comprimento.2. Soluções baseadas em bibliotecas
Muitos exemplos baseados em bibliotecas em outras partes deste tópico são expressões úteis no contexto de sua biblioteca. Do ponto de vista do desempenho, no entanto, não há nada a ganhar em comparação com um código sem biblioteca perfeito, pois todos esses métodos de biblioteca realmente encapsulam um loop for ou ES5
Object.keys
(nativo ou shimmed).3. Otimizando um loop for
A parte mais lenta desse loop for geralmente é a
.hasOwnProperty()
chamada, devido à sobrecarga da chamada de função. Portanto, quando eu apenas quero o número de entradas de um objeto JSON, apenas pulo a.hasOwnProperty()
chamada se souber que nenhum código foi nem será estendidoObject.prototype
.Caso contrário, seu código poderá ser otimizado levemente, tornando
k
local (var k
) e usando o operador prefix-increment (++count
) em vez do postfix.Outra idéia depende do armazenamento em cache do
hasOwnProperty
método:Se isso é mais rápido ou não em um determinado ambiente, é uma questão de benchmarking. Um ganho de desempenho muito limitado pode ser esperado de qualquer maneira.
fonte
var k in myobj
aumentar o desempenho? Até onde eu sei, apenas funções declaram novo escopo em JavaScript. Os in-loops são uma exceção a esta regra?for (var k in myobj) hasOwn.call(myobj, k) && ++count;
ou seja, substituindo a instrução if por um simples &&?Object.getOwnPropertyNames(obj).length
:; muito mais simples.Se você está realmente enfrentando um problema de desempenho, sugiro agrupar as chamadas que adicionam / removem propriedades ao / do objeto com uma função que também aumenta / diminui uma propriedade nomeada adequadamente (size?).
Você só precisa calcular o número inicial de propriedades uma vez e prosseguir a partir daí. Se não houver um problema real de desempenho, não se preocupe. Apenas envolva esse pedaço de código em uma função
getNumberOfProperties(object)
e termine com ela.fonte
Conforme declarado pela Avi Flax https://stackoverflow.com/a/4889658/1047014
fará o truque para todas as propriedades enumeráveis do seu objeto, mas também incluirá as propriedades não enumeráveis que você pode usar
Object.getOwnPropertyNames
. Aqui está a diferença:Conforme declarado aqui, ele tem o mesmo suporte de navegador que
Object.keys
No entanto, na maioria dos casos, talvez você não queira incluir os não numeráveis nesse tipo de operação, mas é sempre bom saber a diferença;)
fonte
Object.getOwnPropertyNames
, você era o único aqui ...Não conheço nenhuma maneira de fazer isso, no entanto, para manter as iterações no mínimo, você pode tentar verificar a existência de
__count__
e, se ela não existir (por exemplo, não o Firefox), poderá iterar sobre o objeto e definir para uso posterior, por exemplo:Dessa forma, qualquer navegador compatível
__count__
usaria isso, e as iterações seriam realizadas apenas para aqueles que não o fazem. Se a contagem for alterada e você não puder fazer isso, sempre poderá transformá-la em uma função:Dessa forma, sempre que você fizer referência a myobj.
__count__
a função será acionada e recalculada.fonte
Object.prototype.__count__
está a ser removido em gecko 1.9.3: whereswalden.com/2010/04/06/... contagem -property-de-objetos-se-a ser removido-/Object.__count__
se foi, e boa viagem também.Para iterar na resposta do Avi Flax, a resposta Object.keys (obj) .length está correta para um objeto que não possui funções vinculadas a ele
exemplo:
versus
etapas para evitar isso:
não coloque funções em um objeto no qual deseja contar o número de chaves
use um objeto separado ou crie um novo objeto especificamente para funções (se você quiser contar quantas funções existem no arquivo usando
Object.keys(obj).length
)Também sim, eu usei o módulo _ ou sublinhado de nodejs no meu exemplo
documentação pode ser encontrada aqui http://underscorejs.org/ , bem como sua fonte no github e várias outras informações
E, finalmente, uma implementação do lodash https://lodash.com/docs#size
_.size(obj)
fonte
Array(obj).length
: Não funciona. // JSFiddle.net/Jhy8M/ #false
, embora ainda não tenha encontrado nenhuma documentação sobre comovar obj = { a: true, b: true }
diferirvar obj = {}; obj.a = true; obj.b = true;
ou simplesmente se uma interpretação / semântica diferente do W3 tiver foi adotado pelo Chrome.como respondido acima:
Object.keys(obj).length
Mas: como agora temos uma classe de mapa real no ES6, sugiro usá-la em vez de usar as propriedades de um objeto.
fonte
Para aqueles que têm o Underscore.js incluído no projeto, você pode:
ou estilo funcional:
fonte
Aqui estão alguns testes de desempenho para três métodos;
https://jsperf.com/get-the-number-of-keys-in-an-object
Object.keys (). Length
20.735 operações por segundo
Muito simples e compatível. É executado rápido, mas caro, porque cria uma nova matriz de chaves, que depois é descartada.
percorrer as teclas
15.734 operações por segundo
Um pouco mais lento, mas nem um pouco próximo do uso da memória, provavelmente melhor se você estiver interessado em otimizar para dispositivos móveis ou outras pequenas máquinas
Usando Mapa em vez de Objeto
953.839.338 operações por segundo
Basicamente, o Map rastreia seu próprio tamanho, então estamos retornando um campo numérico. Muito, muito mais rápido que qualquer outro método. Se você tiver o controle do objeto, converta-o em mapas.
fonte
De: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Você pode adicioná-lo a todos os seus objetos:
Ou um único objeto:
Exemplo:
Adicionado dessa maneira, ele não será exibido nos loops for..in:
Resultado:
Nota: não funciona em navegadores <IE9.
fonte
Como resolvi esse problema é criar minha própria implementação de uma lista básica que mantém um registro de quantos itens estão armazenados no objeto. É muito simples. Algo assim:
fonte
var i = basiclist.count
while(i--){...}
add
substitui um item antigo ou seremove
é chamado por um índice inexistente. Além disso, não é possível verificar se a lista tem um determinado índice seundefined
é um valor de item válido.Você pode usar
Object.keys(data).length
para encontrar o comprimento do objeto JSON com os principais dadosfonte
Para aqueles que possuem o Ext JS 4 em seu projeto, você pode fazer:
A vantagem disso é que ele funcionará em todos os navegadores compatíveis com Ext (incluindo IE6-IE8); no entanto, acredito que o tempo de execução não seja melhor que O (n), como em outras soluções sugeridas.
fonte
Você pode usar:
e
fonte
O OP não especificou se o objeto é um nodeList; se for, você pode simplesmente usar o método length diretamente. Exemplo:
fonte
Se o jQuery acima não funcionar, tente
fonte
Object.Item
não existeEu não acho que isso seja possível (pelo menos não sem o uso de alguns componentes internos). E eu não acho que você ganharia muito otimizando isso.
fonte
Eu tento disponibilizá-lo para todos os objetos como este:
fonte
O Google Closure tem uma boa função para isso ... goog.object.getCount (obj)
documentação do goog.Object Documentation
fonte