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;

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

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

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;
};

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;

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".


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

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. ;)


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++;

20

Basta usar isso para obter length:

Object.keys(myObject).length

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);

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;

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.


15

Usar:

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


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.


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

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--; }}
}

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


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

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>

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


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.


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

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

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

// o/p 3

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.


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/


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()


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.


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

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.


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

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.