Pergunta

O que é a maneira mais rápida para contar o número de chaves / propriedades de um objeto? É possível fazer isso sem a iteração sobre o objeto? ou seja, sem fazer

var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;

(Firefox fez fornecer uma propriedade mágica __count__, mas este estava em algum lugar removido em torno da versão 4).

Foi útil?

Solução

Para fazer isso em qualquer ambiente ES5 compatível , como , Chrome, IE 9 +, Firefox 4+, ou Safari 5 +:

Object.keys(obj).length

Outras dicas

Você pode usar este código:

if (!Object.keys) {
    Object.keys = function (obj) {
        var keys = [],
            k;
        for (k in obj) {
            if (Object.prototype.hasOwnProperty.call(obj, k)) {
                keys.push(k);
            }
        }
        return keys;
    };
}

Em seguida, você pode usar isso em navegadores mais antigos, bem como:

var len = Object.keys(obj).length;

Se você estiver usando Underscore.js você pode usar _ tamanho (graças @douwe):.
_.size(obj)

Como alternativa, você também pode usar _.keys que poderia ser mais claro para alguns:
_.keys(obj).length

Eu recomendo Sublinhado, a sua biblioteca apertado para fazer um monte de coisas básicas. Sempre que possível eles correspondem ECMA5 e adiar para a implementação nativa.

Caso contrário, eu apoiar @ resposta de Avi. Eu editei a adicionar um link para o doc MDC que inclui as chaves () método que você pode adicionar para navegadores não-ECMA5.

A implementação de objeto padrão (propriedades internas ES5.1 Objeto e Métodos ) não requer uma Object para rastrear o número de chaves / propriedades, então não deve haver nenhuma maneira padrão para determinar o tamanho de um Object sem explícita ou implicitamente iteração sobre suas chaves.

Então, aqui estão as alternativas mais comumente utilizados:

1. Object.keys do ECMAScript ()

Object.keys(obj).length; Obras de internamente iteração sobre as chaves para calcular uma matriz temporária e retorna seu comprimento.

  • Pros - legível e sintaxe limpa. Nenhuma biblioteca ou personalizado código necessário, exceto um calço se o suporte nativo é indisponíveis
  • Contras -. Memória sobrecarga devido à criação do array

2. soluções baseadas biblioteca

Muitos exemplos baseados em bibliotecas em outros lugares neste tópico são expressões úteis no contexto de sua biblioteca. Do ponto de vista de desempenho, no entanto, não há nada a ganhar em comparação com um perfeito código não-biblioteca uma vez que todos esses métodos de biblioteca realmente Encapsular qualquer um para-loop ou ES5 Object.keys (nativa ou shimmed).

3. Otimizar um loop for

O parte mais lenta de tal for-loop é geralmente a chamada .hasOwnProperty(), por causa da sobrecarga de chamada de função. Então, quando eu só quero o número de entradas de um objeto JSON, eu simplesmente ignorar a chamada .hasOwnProperty() se eu sei que nenhum código fez nem irá estender Object.prototype.

Caso contrário, seu código pode ser muito ligeiramente otimizado, tornando k local (var k) e usando operador de prefixo-incremento (++count) em vez de postfix.

var count = 0;
for (var k in myobj) if (myobj.hasOwnProperty(k)) ++count;

Outra idéia se baseia em cache o método hasOwnProperty:

var hasOwn = Object.prototype.hasOwnProperty;
var count = 0;
for (var k in myobj) if (hasOwn.call(myobj, k)) ++count;

Se isto é mais rápido ou não em um determinado ambiente é uma questão de avaliação comparativa. Muito ganho de desempenho limitado pode ser esperado de qualquer maneira.

Se você está realmente correndo em um problema desempenho Sugiro envolvendo as chamadas que propriedades Adicionar / Remover de / para o objeto com uma função que também incrementa / decrementa uma apropriadamente chamado (tamanho?) Propriedade.

Você só precisa calcular o número inicial de propriedades uma vez e mover a partir daí. Se não houver um problema de desempenho real, não se incomode. Apenas enrole aquele pedaço de código em um getNumberOfProperties(object) função e ser feito com ele.

Eu não estou ciente de qualquer maneira de fazer isso, no entanto para manter as iterações a um mínimo, você poderia tentar verificando a existência de __count__ e se ele não existe (ou seja, não Firefox), então você pode iterar o objeto e defini-lo para uso posterior por exemplo:

if (myobj.__count__ === undefined) {
  myobj.__count__ = ...
}

Desta forma, qualquer browser que suporte __count__ usaria isso, e iterações só seria realizado para aqueles que não o fazem. Se as mudanças de contagem e você não pode fazer isso, você sempre pode torná-lo uma função:

if (myobj.__count__ === undefined) {
  myobj.__count__ = function() { return ... }
  myobj.__count__.toString = function() { return this(); }
}

Desta forma, a qualquer hora você faz referência myobj.__count__ a função irá disparar e recalcular.

Como afirmado por Avi Linho https://stackoverflow.com/a/4889658/1047014

Object.keys(obj).length

irá fazer o truque para todas as propriedades enumeráveis ??sobre seu objeto, mas também para incluir as propriedades não-enumeráveis ??você pode sim usar o Object.getOwnPropertyNames. Aqui está a diferença:

var myObject = new Object();

Object.defineProperty(myObject, "nonEnumerableProp", {
  enumerable: false
});
Object.defineProperty(myObject, "enumerableProp", {
  enumerable: true
});

console.log(Object.getOwnPropertyNames(myObject).length); //outputs 2
console.log(Object.keys(myObject).length); //outputs 1

console.log(myObject.hasOwnProperty("nonEnumerableProp")); //outputs true
console.log(myObject.hasOwnProperty("enumerableProp")); //outputs true

console.log("nonEnumerableProp" in myObject); //outputs true
console.log("enumerableProp" in myObject); //outputs true

Como afirmado aqui este tem o mesmo suporte ao navegador como Object.keys

No entanto, na maioria dos casos, você pode não querer incluir os nonenumerables neste tipo de operações, mas é sempre bom saber a diferença;)

Para iterate em resposta Avi Linho Object.keys (obj) .length é correto para um objeto que não tenha funções vinculados a ela

exemplo:

obj = {"lol": "what", owo: "pfft"};
Object.keys(obj).length; // should be 2

contra

arr = [];
obj = {"lol": "what", owo: "pfft"};
obj.omg = function(){
    _.each(obj, function(a){
        arr.push(a);
    });
};
Object.keys(obj).length; // should be 3 because it looks like this 
/* obj === {"lol": "what", owo: "pfft", omg: function(){_.each(obj, function(a){arr.push(a);});}} */

passos para evitar este:

  1. não colocar funções em um objeto que você deseja contar o número de teclas no

  2. usar um objeto separado ou fazer um novo objeto especificamente para funções (se você quiser contar quantas funções existem no Object.keys(obj).length arquivo usando)

Também sim eu usei o _ ou módulo sublinhado nodejs no meu exemplo

documentação pode ser encontrada aqui http://underscorejs.org/ , bem como a sua fonte no github e várias outras info

E, finalmente, uma implementação lodash https://lodash.com/docs#size

_.size(obj)

Para aqueles que têm Underscore.js incluído em seu projeto que você pode fazer:

_({a:'', b:''}).size() // => 2

ou estilo funcional:

_.size({a:'', b:''}) // => 2

De: https: //developer.mozilla. org / en / docs / web / JavaScript / Referência / Global_Objects / objeto / defineProperty

Object.defineProperty (obj, prop, descritor)

Você pode adicioná-lo a todos os seus objetos:

Object.defineProperty(Object.prototype, "length", {
    enumerable: false,
    get: function() {
        return Object.keys(this).length;
    }
});

Ou um único objeto:

var myObj = {};
Object.defineProperty(myObj, "length", {
    enumerable: false,
    get: function() {
        return Object.keys(this).length;
    }
});

Exemplo:

var myObj = {};
myObj.name  = "John Doe";
myObj.email = "leaked@example.com";
myObj.length; //output: 2

Adicionado dessa forma, ele não vai ser exibido em for..in laços:

for(var i in myObj) {
     console.log(i + ":" + myObj[i]);
}

Output:

name:John Doe
email:leaked@example.com

Nota:. Não funciona em

como respondida acima: Object.keys(obj).length

Mas: como temos agora uma verdadeira Map classe em ES6, eu sugerem para uso -lo em vez de usar as propriedades de um objeto.

const map = new Map();
map.set("key", "value");
map.size; // THE fastest way

Como eu já resolveu este problema é construir minha própria implementação de uma lista básica, que mantém um registro de quantos itens são armazenados no objeto. É muito simples. Algo parecido com isto:

function BasicList()
{
   var items = {};
   this.count = 0;

   this.add = function(index, item)
   {
      items[index] = item;
      this.count++;
   }

   this.remove = function (index)
   {
      delete items[index];
      this.count--;
   }

   this.get = function(index)
   {
      if (undefined === index)
        return items;
      else
        return items[index];
   }
}

Para aqueles que têm Ext JS 4 em seu projeto você pode fazer:

Ext.Object.getSize(myobj);

A vantagem disso é que ele vai trabalhar em todos os navegadores compatíveis Ext (IE6-IE8 incluído), no entanto, eu acredito que o tempo de execução não melhor do que O (n) é, porém, como acontece com outras soluções sugeridas.

Você pode usar Object.keys(data).length para encontrar o comprimento do objeto JSON ter dados de chave

Se jQuery acima não funcionar, tente

$(Object.Item).length

OP não especificou se o objeto é um nodeList, se for, então você pode simplesmente usar comprimento método nele diretamente. Exemplo:

buttons = document.querySelectorAll('[id=button)) {
console.log('Found ' + buttons.length + ' on the screen'); 

Eu não acho que isso é possível (pelo menos não sem usar alguns internos). E eu não acho que você ganharia muito com a otimização isso.

Eu tento torná-lo disponível para todos objeto como este:

Object.defineProperty(Object.prototype, "length", {
get() {
    if (!Object.keys) {
        Object.keys = function (obj) {
            var keys = [],k;
            for (k in obj) {
                if (Object.prototype.hasOwnProperty.call(obj, k)) {
                    keys.push(k);
                }
            }
            return keys;
        };
    }
    return Object.keys(this).length;
},});

console.log({"Name":"Joe","Age":26}.length) //returns 2

O Google Closure tem uma função agradável para isso ... goog.object.getCount (obj)

olhada Documentação goog.Object

Você pode usar: Object.keys(objectName).length; & Object.values(objectName).length;

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top