Comprimento de um objeto JavaScript

2384

Eu tenho um objeto JavaScript, existe uma maneira de prática recomendada aceita ou incorporada para obter o comprimento desse objeto?

const myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
Gareth Simpson
fonte
15
Literais de objectos no JavaScript são por padrão associativo matrizes por exemplo object.propertyName.propertyValue é o mesmo que o objecto [nomeDaPropriedade] [propertyValue]
neitony
6
Adicionada uma linha no Underscore.js que faz isso: stackoverflow.com/a/11346637/11236
ripper234
31
Quando a resposta da linha for usada, use Object.keys (myArray) .length, como disse o @aeosynth.
Ranadheer Reddy
67
ok, que tal #Object.keys(obj).length
Muhammad Umer
5
Por que object.length não é válido? Retorna o resultado correto para mim.
Adrian M

Respostas:

2624

A resposta mais robusta (ou seja, que captura a intenção do que você está tentando fazer enquanto causa o menor número de erros) seria:

Object.size = function(obj) {
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};

// Get the size of an object
var size = Object.size(myObj);

Existe um tipo de convenção no JavaScript que você não adiciona itens ao Object.prototype , porque ele pode quebrar as enumerações em várias bibliotecas. Adicionar métodos ao Object geralmente é seguro, no entanto.


Aqui está uma atualização a partir de 2016 e implantação generalizada do ES5 e além. Para o IE9 + e todos os outros navegadores modernos compatíveis com ES5 +, você pode usar Object.keys()o código acima:

var size = Object.keys(myObj).length;

Isso não precisa modificar nenhum protótipo existente, pois Object.keys()agora está incorporado.

Editar : os objetos podem ter propriedades simbólicas que não podem ser retornadas pelo método Object.key. Portanto, a resposta seria incompleta sem mencioná-los.

O tipo de símbolo foi adicionado ao idioma para criar identificadores exclusivos para propriedades do objeto. O principal benefício do tipo Symbol é a prevenção de substituições.

Object.keysou Object.getOwnPropertyNamesnão funciona para propriedades simbólicas. Para devolvê-los, você precisa usar Object.getOwnPropertySymbols.

var person = {
  [Symbol('name')]: 'John Doe',
  [Symbol('age')]: 33,
  "occupation": "Programmer"
};

const propOwn = Object.getOwnPropertyNames(person);
console.log(propOwn.length); // 1

let propSymb = Object.getOwnPropertySymbols(person);
console.log(propSymb.length); // 2

fonte
65
@Tres - seu código pode ser quebrado se alguém vier e substituir a propriedade 'size' sem saber que você já a declarou em algum lugar do código, por isso sempre vale a pena verificar se já está definido #
vsync
19
@ vsync Você está muito correto. Um deve sempre implementar checagens necessárias :)
Tres
132
Por que todo mundo está ignorando isso:Object.keys(obj).length
Muhammad Umer
33
@ MuhammadUmer Provavelmente porque esse método nem existia quando esta resposta foi escrita. Ainda hoje, o uso provavelmente exigirá um polyfill para navegadores antigos.
Chris Hayes
21
@stonyau IE8, IE9, IE10 são navegadores mortos que não recebem suporte da Microsoft. O usuário IE8, IE9, IE10 recebe uma notificação da Microsoft de que usa um navegador antigo e não suportado e deve esperar que essas coisas não funcionem para eles. support.microsoft.com/en-us/kb/3123303
Lukas Liesis
1708

Se você sabe que não precisa se preocupar com hasOwnPropertyverificações, faça isso de maneira muito simples:

Object.keys(myArray).length
aeosynth
fonte
23
Por que não? pelo que sei, é um padrão: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
vsync
104
Não é um método implementado universalmente , mas você pode verificar qual navegador é compatível com esta tabela .
aeosynth
51
Não há suporte para o IE8 = não é possível.
precisa saber é o seguinte
22
tempo para mudar para o Firefox = infelizmente, você mudar não significa que usuários do seu site vai ...
mdup
82
@ ripper234 no IE support = time to polyfill #
John Dvorak
287

Atualizado : se você estiver usando o Underscore.js (recomendado, é leve!), Poderá fazer

_.size({one : 1, two : 2, three : 3});
=> 3

Caso contrário , e você não quer mexer nas propriedades do objeto por qualquer motivo, e já está usando o jQuery, um plug-in é igualmente acessível:

$.assocArraySize = function(obj) {
    // http://stackoverflow.com/a/6700/11236
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};
ripper234
fonte
7
_.size()foi a solução perfeita para o meu projeto Meteor , que tem suporte a underscore.js.
tokyovariable
4
Uso sublinhado e este post me lembrou que não o estou usando o suficiente neste projeto. Se você manipular objetos, deverá ter underscore.js disponível.
Jbolanos #
3
Sublinhado> (todos - ['lo-dash']))
Rayjax 11/04
underscorejs, coisas que deveriam estar sob js :)
minhajul
1
@ Babydead para distinguir propriedades reais do objeto versus propriedades herdadas. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
ripper234
56

Aqui está a solução com mais navegadores.

Isso é melhor do que a resposta aceita porque usa Object.keys nativo, se existir. Portanto, é o mais rápido para todos os navegadores modernos.

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

Object.keys(obj).length;
Joon
fonte
6
Object.keys()retorna uma matriz que contém os nomes apenas das propriedades enumeráveis. Se você deseja uma matriz com TODAS as propriedades, deve usar Object.getOwnPropertyNames(). Veja developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
John Slegers 7/16
35

Não sou especialista em JavaScript, mas parece que você precisaria percorrer os elementos e contá-los, pois Object não possui um método de comprimento:

var element_count = 0;
for (e in myArray) {  if (myArray.hasOwnProperty(e)) element_count++; }

@palmsey: Para ser justo com o OP, a documentação JavaScript realmente se refere explicitamente ao uso de variáveis ​​do tipo Object dessa maneira como "matrizes associativas".

jj33
fonte
8
Não funcionará, porque contará métodos também, que são adicionados através do protótipo.
Lajos Meszaros
30

Esse método obtém todos os nomes de propriedades do seu objeto em uma matriz, para que você possa obter o comprimento dessa matriz igual ao comprimento das chaves do seu objeto.

Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2
venkat7668
fonte
O método de chaves @PatrickRoberts não retorna propriedades da cadeia de protótipos. Então, por que a necessidade de hasOwnProperty aqui. Também getOwnProperty voltará propriedades escondidas, como comprimento é na matriz, etc.
Muhammad Umer
24

Para não mexer com o protótipo ou outro código, você pode criar e estender seu próprio objeto:

function Hash(){
    var length=0;
    this.add = function(key, val){
         if(this[key] == undefined)
         {
           length++;
         }
         this[key]=val;
    }; 
    this.length = function(){
        return length;
    };
}

myArray = new Hash();
myArray.add("lastname", "Simpson");
myArray.add("age", 21);
alert(myArray.length()); // will alert 2

Se você sempre usar o método add, a propriedade length estará correta. Se você estiver preocupado com o fato de você ou outras pessoas esquecerem de usá-la, adicione o contador de propriedades que outras pessoas postaram no método length também.

Claro, você sempre pode substituir os métodos. Mas mesmo se você o fizer, seu código provavelmente falhará notavelmente, facilitando a depuração. ;)

DanMan
fonte
Eu acho que esta é a melhor solução, uma vez que não requer looping com 'para' que poderia ser caro se a matriz é grande
Emeka Mbah
20

Veja como e não se esqueça de verificar se a propriedade não está na cadeia de protótipos:

var element_count = 0;
for(var e in myArray)
    if(myArray.hasOwnProperty(e))
        element_count++;
doekman
fonte
20

Basta usar isso para obter length:

Object.keys(myObject).length
saurabhgoyal795
fonte
7
por favor, explique como sua resposta difere de stackoverflow.com/a/6700/8632727
Patata
3
Você também não deve realmente ser nomear seu objetomyArray
Barry Michael Doyle
2
@BarryMichaelDoyle eu mudei isso:) #
saurabhgoyal795
Bom, é sempre melhor nomear suas variáveis ​​de acordo com o que elas realmente são. Torna seu código mais legível para outros desenvolvedores.
Barry Michael Doyle #
4
Antes da edição "myArray" -> "myObject", isso era idêntico à segunda resposta mais votada.
Yunnosch
16

Aqui está uma solução completamente diferente que funcionará apenas em navegadores mais modernos (IE9 +, Chrome, Firefox 4+, Opera 11.60+, Safari 5.1+)

Veja jsFiddle

Configure sua classe Matriz Associativa

/**
 * @constructor
 */
AssociativeArray = function () {};

// Make the length property work
Object.defineProperty(AssociativeArray.prototype, "length", {
    get: function () {
        var count = 0;
        for (var key in this) {
            if (this.hasOwnProperty(key))
                count++;
        }
        return count;
    }
});

Agora você pode usar esse código da seguinte maneira ...

var a1 = new AssociativeArray();
a1["prop1"] = "test";
a1["prop2"] = 1234;
a1["prop3"] = "something else";
alert("Length of array is " + a1.length);
Aliado
fonte
Eu acho que isso não é seguro. Por exemplo, ele não pode ter um elemento com uma chave "length", a instrução a1 ["length"] = "Hello world"; falha ao armazenar a entrada. Também a instrução a1 ["hasOwnProperty"] = "some prop"; totalmente rompe a função
Panos Theof
3
@PanosTheof Eu não acho que você gostaria que ele armazenasse o valor se você usasse a lengthpropriedade, qualquer código que a usasse teria que garantir que não tentasse armazenar contra length, mas acho que seria o mesmo se fosse uma matriz padrão também. Substituir hasOwnPropertyqualquer objeto provavelmente produziria um resultado indesejado.
Ally
16

<script>
myObj = {"key1" : "Hello", "key2" : "Goodbye"};
var size = Object.keys(myObj).length;
console.log(size);
</script>

<p id="myObj">The number of <b>keys</b> in <b>myObj</b> are: <script>document.write(size)</script></p>

Isso funciona para mim:

var size = Object.keys(myObj).length;
Giovanni G. PY
fonte
15

Em alguns casos, é melhor armazenar apenas o tamanho em uma variável separada. Especialmente, se você estiver adicionando à matriz por um elemento em um só lugar e puder aumentar facilmente o tamanho. Obviamente, funcionaria muito mais rápido se você precisar verificar o tamanho com frequência.

Jānis Elmeris
fonte
15

Usar:

var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
obj = Object.keys(myArray).length;
console.log(obj)

Mahendra Kulkarni
fonte
14

@palmsey: Para ser justo com o OP, os documentos javascript na verdade se referem explicitamente ao uso de variáveis ​​do tipo Object dessa maneira como "matrizes associativas".

Para ser justo com @palmsey, ele estava certo, eles não são matrizes associativas, são definitivamente objetos :) - fazendo o trabalho de uma matriz associativa. Mas no que diz respeito ao ponto mais amplo, você definitivamente parece ter o direito de acordo com este artigo bastante interessante que eu descobri:

"Matrizes associativas" do JavaScript consideradas prejudiciais

Mas, de acordo com tudo isso, a resposta aceita não é uma prática ruim?

Especifique uma função size () do protótipo para Object

Se alguma outra coisa foi adicionada ao objeto .prototype, o código sugerido falhará:

<script type="text/javascript">
Object.prototype.size = function () {
  var len = this.length ? --this.length : -1;
    for (var k in this)
      len++;
  return len;
}
Object.prototype.size2 = function () {
  var len = this.length ? --this.length : -1;
    for (var k in this)
      len++;
  return len;
}
var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
alert("age is " + myArray["age"]);
alert("length is " + myArray.size());
</script>

Eu não acho que essa resposta deva ser aceita, pois não pode ser confiável funcionar se você tiver outro código em execução no mesmo contexto de execução. Para fazer isso de maneira robusta, certamente você precisará definir o método de tamanho no myArray e verificar o tipo de membros à medida que itera.

Polsonby
fonte
13

Se você precisar de uma estrutura de dados associativa que exponha seu tamanho, use melhor um mapa em vez de um objeto.

const myMap = new Map();
myMap.set("firstname", "Gareth");
myMap.set("lastname", "Simpson");
myMap.set("age", 21);
myMap.size; // 3
Oriol
fonte
11

Que tal algo assim -

function keyValuePairs() {
    this.length = 0;
    function add(key, value) { this[key] = value; this.length++; }
    function remove(key) { if (this.hasOwnProperty(key)) { delete this[key]; this.length--; }}
}
Jerry
fonte
11

Se tivermos o hash

hash = {"a": "b", "c": "d"};

podemos obter o comprimento usando o comprimento das chaves, que é o comprimento do hash:

keys (hash) .length

abo-elleef
fonte
2
Esta é uma ótima resposta, no entanto, não consigo encontrar nenhuma documentação para esta função de teclas. Portanto, não posso confiar no suporte a vários navegadores.
chim
1
Infelizmente, essa não é uma resposta tão boa quanto eu pensava! Acontece que a função de teclas está disponível apenas nos consoles da web chrome e firefox. Se você colocar esse código em um script, ele falhará com o Uncaught ReferenceError: keys não está definido
chim
1
Como isso é diferente da resposta do aeosynth ?
Peter Mortensen
11
var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
  1. Object.values ​​(myObject) .length
  2. Object.entries (myObject) .length
  3. Object.keys (myObject) .length
tdjprog
fonte
Qual deles é o mais rápido entre os acima 3.
siluveru Kiran Kumar
Object.values (meuObjeto) .length
tdjprog
como podemos dizer que Object.values (myObject) .length é mais rápido existe qualquer exemplo de Graças, @tdjprog
siluveru Kiran Kumar
tente isso no console:var myObject = {}; for (let i=0; i<10000000; i++) myObject[i] = i;
tdjprog
por que Object.values ​​(myObject) .length mais rápido, onde Object.entries (myObject) .length não fornece saída, mesmo depois de algum tempo, qual é o motivo aqui? Obrigado @tdjprog
siluveru kiran kumar
10

Se você estiver usando o AngularJS 1.x, poderá fazer as coisas da maneira AngularJS criando um filtro e usando o código de qualquer um dos outros exemplos, como os seguintes:

// Count the elements in an object
app.filter('lengthOfObject', function() {
  return function( obj ) {
    var size = 0, key;
    for (key in obj) {
      if (obj.hasOwnProperty(key)) size++;
    }
   return size;
 }
})

Uso

No seu controlador:

$scope.filterResult = $filter('lengthOfObject')($scope.object)

Ou na sua opinião:

<any ng-expression="object | lengthOfObject"></any>
pcnate
fonte
4
O OP não solicitou uma versão do AngularJS. Esta não é uma resposta válida para a pergunta.
Francisco Hodge
10

A maneira mais simples é assim

Object.keys(myobject).length

onde myobject é o objeto do que você quer o comprimento

Mithu A Quayium
fonte
2
Parece ser apenas uma repetição desta resposta existente .
Pang
A @Pang concordou e não fornece nenhum contexto adicional, como outras respostas.
Mystical
8

Se você não se preocupa em oferecer suporte ao Internet Explorer 8 ou inferior, pode obter facilmente o número de propriedades em um objeto aplicando as duas etapas a seguir:

  1. Execute Object.keys()para obter uma matriz que contenha apenas os nomes das propriedades enumeráveis ou Object.getOwnPropertyNames()se você também quiser incluir os nomes das propriedades não enumeráveis.
  2. Obtenha a .lengthpropriedade dessa matriz.

Se você precisar fazer isso mais de uma vez, poderá envolver essa lógica em uma função:

function size(obj, enumerablesOnly) {
    return enumerablesOnly === false ?
        Object.getOwnPropertyNames(obj).length :
        Object.keys(obj).length;
}

Como usar esta função específica:

var myObj = Object.create({}, {
    getFoo: {},
    setFoo: {}
});
myObj.Foo = 12;

var myArr = [1,2,5,4,8,15];

console.log(size(myObj));        // Output : 1
console.log(size(myObj, true));  // Output : 1
console.log(size(myObj, false)); // Output : 3
console.log(size(myArr));        // Output : 6
console.log(size(myArr, true));  // Output : 6
console.log(size(myArr, false)); // Output : 7

Veja também este Fiddle para uma demonstração.

John Slegers
fonte
8

Use Object.keys(myObject).lengthpara obter o comprimento do objeto / matriz

var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;

console.log(Object.keys(myObject).length); //3
shaheb
fonte
8
const myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;

console.log(Object.keys(myObject).length)

// o/p 3
Dev216
fonte
7

Uma variação em alguns dos itens acima é:

var objLength = function(obj){    
    var key,len=0;
    for(key in obj){
        len += Number( obj.hasOwnProperty(key) );
    }
    return len;
};

É uma maneira um pouco mais elegante de integrar o hasOwnProp.

Wade Harrell
fonte
6

Aqui está uma versão diferente da resposta de James Cogan. Em vez de passar um argumento, apenas protótipo da classe Object e torne o código mais limpo.

Object.prototype.size = function () {
    var size = 0,
        key;
    for (key in this) {
        if (this.hasOwnProperty(key)) size++;
    }
    return size;
};

var x = {
    one: 1,
    two: 2,
    three: 3
};

x.size() === 3;

Exemplo de jsfiddle: http://jsfiddle.net/qar4j/1/

Sherzod
fonte
6
Object.prototype- péssima ideia.
Dziad Borowy
@tborychowski você pode explicar por que?
Mohamad
Aqui está um artigo: bit.ly/1droWrG . Não estou dizendo que não deve ser feito, apenas que você precisa conhecer todas as repercussões antes de fazer isso.
Dziad Borowy
Se você deseja estender protótipos embutidos ou preencher uma propriedade (por exemplo, uma correção de macaco), faça-o corretamente: para compatibilidade direta, verifique se a propriedade existe primeiro e torne a propriedade não enumerável para que as próprias chaves de objetos construídos não são poluídos. Para métodos, use métodos reais . Minha recomendação: siga estes exemplos que demonstram como adicionar um método que se comporte o mais próximo possível dos métodos internos.
user4642212
5

Você pode simplesmente usar Object.keys(obj).lengthem qualquer objeto para obter seu comprimento. Object.keys retorna uma matriz contendo todas as chaves (propriedades) do objeto, que podem ser úteis para encontrar o comprimento desse objeto usando o comprimento da matriz correspondente. Você pode até escrever uma função para isso. Vamos ser criativos e escrever um método para ele também (junto com uma propriedade getter mais conveniente):

function objLength(obj)
{
  return Object.keys(obj).length;
}

console.log(objLength({a:1, b:"summit", c:"nonsense"}));

// Works perfectly fine
var obj = new Object();
obj['fish'] = 30;
obj['nullified content'] = null;
console.log(objLength(obj));

// It also works your way, which is creating it using the Object constructor
Object.prototype.getLength = function() {
   return Object.keys(this).length;
}
console.log(obj.getLength());

// You can also write it as a method, which is more efficient as done so above

Object.defineProperty(Object.prototype, "length", {get:function(){
    return Object.keys(this).length;
}});
console.log(obj.length);

// probably the most effictive approach is done so and demonstrated above which sets a getter property called "length" for objects which returns the equivalent value of getLength(this) or this.getLength()

Místico
fonte
3
Como isso é diferente da resposta do aeosynth ?
Peter Mortensen
É porque mostra como torná-lo uma função e um método de objeto global (mais orientado a objetos e usa alguma forma de encapsulamento); no entanto, a resposta do aeosynth não.
Mystical
Se você deseja estender protótipos embutidos ou preencher uma propriedade (por exemplo, uma correção de macaco), faça-o corretamente: para compatibilidade direta, verifique se a propriedade existe primeiro e torne a propriedade não enumerável para que as próprias chaves de objetos construídos não são poluídos. Para métodos, use métodos reais . Minha recomendação: siga estes exemplos que demonstram como adicionar um método que se comporte o mais próximo possível dos métodos internos.
user4642212
Além disso, como escrever um método é “mais eficiente”?
user4642212
5

Você sempre pode fazer Object.getOwnPropertyNames(myObject).lengthpara obter o mesmo resultado [].lengthque daria para a matriz normal.

Pian0_M4n
fonte
1
Object.keys()retorna uma matriz que contém os nomes apenas das propriedades enumeráveis. Se você deseja uma matriz com TODAS as propriedades, deve usar Object.getOwnPropertyNames(). Veja developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
John Slegers 7/16
3
Como isso é diferente da resposta do aeosynth ?
Peter Mortensen
4

Podemos encontrar o comprimento do objeto usando:

Object.values(myObject).length
solanki ...
fonte
4

Um pouco tarde para o jogo, mas uma boa maneira de conseguir isso (apenas no IE9 +) é definir um getter mágico na propriedade length:

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

E você pode usá-lo assim:

var myObj = { 'key': 'value' };
myObj.length;

Daria 1.

MacroMan
fonte
1
Argumentos contra a modificação do protótipo à parte, eu pessoalmente nunca tive um bug causado por ele e para mim é um dos pontos fortes do JavaScript.
MacroMan 13/08/19
3

Abaixo está uma versão da resposta de James Coglan no CoffeeScript para aqueles que abandonaram o JavaScript direto :)

Object.size = (obj) ->
  size = 0
  size++ for own key of obj
  size
Eric Anderson
fonte
1
Você provavelmente quis dizer size++ for own key of obj( own keysendo açúcar de sintaxe no CoffeeScript). Usar hasOwnPropertydiretamente do objeto é perigoso, pois quebra quando o objeto realmente possui essa propriedade.
21813 Konrad Borowski
2
O OP não pediu uma versão do CoffeeScript, nem está marcado como tal. Esta não é uma resposta válida para a pergunta.
Francisco Hodge