Numero di elementi in un oggetto javascript


104

C'è un modo per ottenere (da qualche parte) il numero di elementi in un oggetto javascript ?? (cioè complessità a tempo costante).

Non riesco a trovare una proprietà o un metodo che recuperi tali informazioni. Finora posso solo pensare di fare un'iterazione attraverso l'intera raccolta, ma è tempo lineare.
È strano che non ci sia accesso diretto alle dimensioni dell'oggetto, non credi.

EDIT:
sto parlando Objectdell'oggetto (non degli oggetti in generale):

var obj = new Object ;

5
Già risposto qui stackoverflow.com/questions/126100/... Object.keys (obj) .length
ghette

Risposte:


155

Sebbene le implementazioni JS possano tenere traccia di tale valore internamente, non esiste un modo standard per ottenerlo.

In passato, la variante Javascript di Mozilla ha esposto il non standard__count__ , ma è stata rimossa con la versione 1.8.5.

Per lo scripting cross-browser sei bloccato con l'iterazione esplicita sulle proprietà e il controllo hasOwnProperty():

function countProperties(obj) {
    var count = 0;

    for(var prop in obj) {
        if(obj.hasOwnProperty(prop))
            ++count;
    }

    return count;
}

In caso di implementazioni compatibili con ECMAScript 5, questo può anche essere scritto come (Kudos to Avi Flax )

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

Tieni presente che perderai anche le proprietà che non sono enumerabili (ad esempio, un array length).

Se stai utilizzando un framework come jQuery, Prototype, Mootools, $ qualunque-il-più recente-hype, controlla se sono dotati della loro API di raccolte, che potrebbe essere una soluzione migliore al tuo problema rispetto all'utilizzo di oggetti JS nativi.


11
Dannazione, dimentico sempre hasOwnProperty. Troppo tempo in .NET Land ti dico. +1
annakata,

2
jQuery utilizza un oggetto per le sue raccolte che ottiene dalle query ed espone quel valore con una proprietà length.
Nosredna,

6
Firefox4 non __count__c'è più :(
Timo Huovinen

1
C'è un modo per farlo senza un for in? Sono nello stesso tipo di legame, ma mi piacerebbe che superasse JSLint se possibile.
lampione

1
perché ne abbiamo bisogno hasOwnProperty()?
swisswiss

100

Per farlo in qualsiasi ambiente compatibile con ES5

Object.keys(obj).length

(Supporto del browser da qui )
(Doc on Object.keys qui , include il metodo che puoi aggiungere a browser non ECMA5)


2
Questa non è la domanda giusta su cui porre questa risposta. Con questo stai prendendo tutte le chiavi dell'oggetto, inserendole in un array appena creato e quindi recuperando la proprietà length da quel nuovo array.
GetFree

13
Potrebbe non essere il più efficiente dal punto di vista programmatico, ma è il più efficiente per gli sviluppatori.
superluminario

9

se stai già usando jQuery nella tua build, fallo semplicemente:

$(yourObject).length

Funziona bene per me sugli oggetti e avevo già jQuery come dipendenza.


5
Strano ... questo non funziona per me. Ottengo sempre 1. La risposta di ZelkiN funziona per me.
mike rodent

3
Questo codice restituisce sempre 1. Solo 1 oggetto. Non conta gli elementi in esso
BeRocket

5
function count(){
    var c= 0;
    for(var p in this) if(this.hasOwnProperty(p))++c;
    return c;
}

var O={a: 1, b: 2, c: 3};

count.call(O);

2

Per quanto ne so, non è possibile eseguire questa operazione in modo affidabile, a meno che non si passi a un array. Il che, onestamente, non sembra strano: mi sembra piuttosto semplice che gli array siano numerabili e gli oggetti no.

Probabilmente il più vicino che otterrai è qualcosa del genere

// Monkey patching on purpose to make a point
Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this ) i++;
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 3

Ma questo crea problemi, o almeno domande. Vengono conteggiate tutte le proprietà create dall'utente, inclusa la funzione _length stessa! E mentre in questo semplice esempio potresti evitarlo semplicemente usando una normale funzione, ciò non significa che puoi impedire ad altri script di farlo. Allora cosa fai? Ignorare le proprietà della funzione?

Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this )
  {
      if ( 'function' == typeof this[p] ) continue;
      i++;
  }
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 2

Alla fine, penso che dovresti probabilmente abbandonare l'idea di rendere i tuoi oggetti numerabili e trovare un altro modo per fare qualunque cosa tu stia facendo.


8
PERICOLO SARÀ ROBINSON! Fare NON proto contro oggetto! Tutto discende da Object, paralizzerai l'elaborazione del client in questo modo se stai facendo una quantità considerevole di lavoro JS.
annakata

5
Uh ... non hai letto la parte in cui ho scritto in un commento "Scimmia che rattoppa apposta per fare un punto" - dai, l'ho fatto deliberatamente in modo che le persone non si ribaltassero un po 'al riguardo. Inoltre, anche se non sostengo il patching delle scimmie, fraintendi come funziona la catena del prototipo in Javascript se pensi che ciò causerebbe problemi di prestazioni video.yahoo.com/watch/111585/1027823
Peter Bailey,

Quindi .. questo è un fare o un non fare?
OscarRyz

In "Javascript: The Good Parts", crea prototipi di oggetti con un metodo "create ()". Credo che sia il libro definitivo su Javascript.
Chris Dutrow

1

Il concetto di numero / lunghezza / dimensionalità non ha davvero senso per un oggetto e averne bisogno suggerisce che vuoi davvero un array per me.

Modifica: mi ha fatto notare che vuoi un O (1) per questo. Per quanto ne so, non esiste alcun modo del genere, temo.


Ha proposto di iterare se stesso, quale è questa soluzione. Aveva bisogno di un modo O (1) per raggiungere questo obiettivo ...
Thomas Hansen,

Hai proprio ragione. Davvero dovrebbe leggere le domande in modo più approfondito.
annakata

In realtà, gli oggetti sono la cosa più vicina a una mappa che c'è in JS. Le mappe hanno una lunghezza.
Cristian Vrabie
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.