Lunghezza di un oggetto JavaScript


2384

Ho un oggetto JavaScript, esiste un metodo di best practice integrato o accettato per ottenere la lunghezza di questo oggetto?

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

15
I valori letterali degli oggetti in JavaScript sono array associativi predefiniti, ad esempio object.propertyName.propertyValue è lo stesso dell'oggetto object [propertyName] [propertyValue]
neitony

6
Aggiunto un one-liner in Underscore.js che fa questo: stackoverflow.com/a/11346637/11236
ripper234

31
Una volta che si risponde alla riga, utilizzare Object.keys (myArray) .length come ha detto @aeosynth.
Ranadheer Reddy,

67
ok, che ne diciObject.keys(obj).length
Muhammad Umer del

5
Perché object.length non è valido? Restituisce il risultato corretto per me.
Adrian M,

Risposte:


2624

La risposta più efficace (ovvero che cattura l'intento di ciò che stai cercando di fare causando il minor numero di bug) sarebbe:

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

C'è una sorta di convenzione in JavaScript che non aggiunge cose a Object.prototype , perché può interrompere le enumerazioni in varie librerie. Tuttavia, l'aggiunta di metodi a Object è generalmente sicura.


Ecco un aggiornamento a partire dal 2016 e un'implementazione diffusa di ES5 e oltre. Per IE9 + e tutti gli altri moderni browser compatibili con ES5 +, è possibile utilizzare in Object.keys()modo che il codice sopra riportato diventi:

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

Questo non deve modificare alcun prototipo esistente poiché Object.keys()è ora incorporato.

Modifica : gli oggetti possono avere proprietà simboliche che non possono essere restituite tramite il metodo Object.key. Quindi la risposta sarebbe incompleta senza menzionarli.

Il tipo di simbolo è stato aggiunto al linguaggio per creare identificatori univoci per le proprietà degli oggetti. Il principale vantaggio del tipo di simbolo è la prevenzione delle sovrascritture.

Object.keyso Object.getOwnPropertyNamesnon funziona per le proprietà simboliche. Per restituirli è necessario utilizzare 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 - il tuo codice può essere infranto se qualcuno arrivasse e scavalcasse la proprietà 'size' senza sapere che l'hai già dichiarato da qualche parte nel codice, quindi vale sempre la pena verificare se è già stato definito
vsync

19
@vsync Hai ragione. Bisogna sempre attuare i necessari controlli di integrità :)
Tres,

132
Perché tutti lo ignorano:Object.keys(obj).length
Muhammad Umer,

33
@MuhammadUmer Probabilmente perché quel metodo non esisteva nemmeno quando è stata scritta questa risposta. Ancora oggi, usarlo richiederà probabilmente un riempimento automatico per i vecchi browser.
Chris Hayes,

21
@stonyau IE8, IE9, IE10 sono browser morti che non ottengono supporto da Microsoft. L'utente di IE8, IE9, IE10 riceve una notifica da Microsoft, che utilizza un browser vecchio e non supportato e dovrebbe aspettarsi che le cose non funzionino per loro. support.microsoft.com/en-us/kb/3123303
Lukas Liesis,

1708

Se sai che non devi preoccuparti dei hasOwnPropertycontrolli, puoi farlo molto semplicemente:

Object.keys(myArray).length

23
perchè no? da quello che so, è uno standard: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
vsync,

104
Non è un metodo implementato universalmente , ma puoi verificare quale browser lo supporta con questa tabella .
aeosynth,

51
Nessun supporto IE8 = no go.
ripper234

22
tempo di passare a firefox = sfortunatamente, il passaggio non significa che gli utenti del tuo sito Web ...
mdup

82
@ ripper234 no IE support = time to polyfill
John Dvorak,

287

Aggiornato : se stai usando Underscore.js (consigliato, è leggero!), Allora puoi semplicemente farlo

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

In caso contrario , e non vuoi fare confusione con le proprietà Object per qualsiasi motivo e stai già utilizzando jQuery, un plug-in è ugualmente accessibile:

$.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()è stata la soluzione perfetta per il mio progetto Meteor , che ha il supporto underscore.js.
tokyovariable

4
Uso il trattino basso e questo post mi ha appena ricordato che non lo sto usando abbastanza in questo progetto. Se gestisci gli oggetti, dovresti avere underscore.js disponibile.
jbolanos,

3
Underscore> (all - ['lo-dash'])
Rayjax l'

underscorejs, cose che dovrebbero essere sotto js :)
minhajul

1
@Babydead per distinguere le proprietà reali dell'oggetto da quelle ereditate. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
ripper234

56

Ecco la soluzione più cross-browser.

È meglio della risposta accettata perché utilizza Object.keys nativo se esiste. Pertanto, è il più veloce per tutti i browser moderni.

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()restituisce un array che contiene solo i nomi delle proprietà enumerabili. Se si desidera un array con TUTTE le proprietà, è necessario utilizzare Object.getOwnPropertyNames()invece. Vedi developer.mozilla.org/it/docs/Web/JavaScript/Reference/…
John Slegers

35

Non sono un esperto di JavaScript, ma sembra che dovresti scorrere gli elementi e contarli poiché Object non ha un metodo di lunghezza:

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

@palmsey: In tutta onestà all'OP, la documentazione JavaScript in realtà si riferisce esplicitamente all'uso delle variabili di tipo Object in questo modo come "array associativi".


8
Non funzionerà, perché conterà anche i metodi che vengono aggiunti tramite prototipo.
Lajos Meszaros,

30

Questo metodo ottiene tutti i nomi delle proprietà del tuo oggetto in un array, quindi puoi ottenere la lunghezza di tale array che è uguale alla lunghezza delle chiavi del tuo oggetto.

Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2

Il metodo delle chiavi @PatrickRoberts non restituisce proprietà dalla catena di prototipi. Quindi, perché la necessità di hasOwnProperty qui. Anche getOwnProperty restituirà proprietà nascoste, poiché la lunghezza è nella matrice, ecc.
Muhammad Umer,

24

Per non scherzare con il prototipo o altro codice, è possibile creare ed estendere il proprio oggetto:

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 si utilizza sempre il metodo add, la proprietà length sarà corretta. Se sei preoccupato che tu o gli altri dimenticate di usarlo, è possibile aggiungere il contatore di proprietà che anche gli altri hanno pubblicato nel metodo length.

Ovviamente, puoi sempre sovrascrivere i metodi. Ma anche se lo fai, il tuo codice probabilmente fallirebbe notevolmente, rendendo facile il debug. ;)


Penso che questa sia la soluzione migliore in quanto non richiede il looping con 'for' che potrebbe essere costoso se l'array è grande
Emeka Mbah

20

Ecco come e non dimenticare di verificare che la proprietà non si trovi nella catena di prototipi:

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

20

Basta usare questo per ottenere length:

Object.keys(myObject).length

7
spiega in che modo la tua risposta differisce da stackoverflow.com/a/6700/8632727
Patata,

3
Inoltre, non dovresti davvero dare un nome al tuo oggettomyArray
Barry Michael Doyle,

2
@BarryMichaelDoyle l'ho cambiato :)
saurabhgoyal795

Bene, è sempre meglio nominare le variabili in base a ciò che sono realmente. Rende il tuo codice più leggibile per gli altri sviluppatori.
Barry Michael Doyle il

4
Prima della modifica di "myArray" -> "myObject", questa era identica alla risposta con il secondo voto più alto.
Yunnosch,

16

Ecco una soluzione completamente diversa che funzionerà solo con browser più moderni (IE9 +, Chrome, Firefox 4+, Opera 11.60+, Safari 5.1+)

Vedi jsFiddle

Imposta la tua classe di array associativo

/**
 * @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;
    }
});

Ora puoi usare questo codice come segue ...

var a1 = new AssociativeArray();
a1["prop1"] = "test";
a1["prop2"] = 1234;
a1["prop3"] = "something else";
alert("Length of array is " + a1.length);

Penso che non sia sicuro. Ad esempio, non può avere un elemento con una chiave di "lunghezza", l'istruzione a1 ["lunghezza"] = "Ciao mondo"; non riesce a memorizzare la voce. Anche l'istruzione a1 ["hasOwnProperty"] = "some prop"; interrompe totalmente la funzione
Panos Theof,

3
@PanosTheof Non penso che vorresti che memorizzasse il valore se avessi usato la lengthproprietà, qualsiasi codice che la usasse avrebbe dovuto garantire che non provasse e archiviasse length, ma immagino che sarebbe lo stesso se fosse anche un array standard. Sostituire hasOwnPropertyqualsiasi oggetto produrrebbe molto probabilmente un risultato indesiderato.
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>

Questo funziona per me:

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

15

In alcuni casi è meglio archiviare le dimensioni in una variabile separata. Soprattutto, se si aggiunge all'array di un elemento in un unico punto e si può facilmente aumentare la dimensione. Ovviamente funzionerebbe molto più velocemente se devi controllare spesso le dimensioni.


15

Uso:

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


14

@palmsey: In tutta onestà all'OP, i documenti javascript in realtà si riferiscono esplicitamente all'uso delle variabili di tipo Object in questo modo come "array associativi".

E in tutta onestà con @palmsey aveva ragione, non sono array associativi, sono sicuramente oggetti :) - fanno il lavoro di un array associativo. Ma per quanto riguarda il punto più ampio sembri sicuramente averne il diritto secondo questo articolo piuttosto bello che ho trovato:

JavaScript "array associativi" considerati dannosi

Ma secondo tutto ciò, la risposta accettata non è di per sé cattiva pratica?

Specificare una funzione size () del prototipo per Object

Se qualcos'altro è stato aggiunto all'oggetto .prototype, il codice suggerito non riuscirà:

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

Non credo che la risposta dovrebbe essere quella accettata in quanto non ci si può fidare che funzioni se si ha un altro codice in esecuzione nello stesso contesto di esecuzione. Per farlo in modo robusto, sicuramente dovresti definire il metodo di dimensione all'interno di myArray e verificare il tipo di membri mentre esegui l'iterazione attraverso di essi.


13

Se hai bisogno di una struttura di dati associativi che ne esponga le dimensioni, usa meglio una mappa anziché un oggetto.

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

11

Che dire di qualcosa del genere -

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 abbiamo l'hash

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

possiamo ottenere la lunghezza usando la lunghezza dei tasti che è la lunghezza dell'hash:

chiavi (hash) .length


2
Questa è un'ottima risposta, tuttavia non riesco a trovare alcuna documentazione per questa funzione di tasti. Quindi non posso essere fiducioso sul supporto cross browser.
chim

1
Sfortunatamente, questa non è una buona risposta come pensavo inizialmente! Si scopre che la funzione dei tasti è disponibile solo nelle console web Chrome e Firefox. Se inserisci questo codice in uno script, allora fallirà con Uncaught ReferenceError: le chiavi non sono definite
chim


1
In che cosa differisce dalla risposta di eosynth ?
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

Quale è più veloce tra i precedenti 3.
siluveru kiran kumar il

Object.values ​​(myObject) .length
tdjprog

come possiamo dire che Object.values ​​(myObject) .length è più veloce c'è qualche esempio Grazie, @tdjprog
siluveru kiran kumar

prova questo in console:var myObject = {}; for (let i=0; i<10000000; i++) myObject[i] = i;
tdjprog

perché Object.values ​​(myObject) .length più velocemente, dove Object.entries (myObject) .length non dà output anche dopo qualche tempo qual è la ragione qui? Grazie @tdjprog
siluveru kiran kumar il

10

Se stai usando AngularJS 1.x puoi fare le cose nel modo AngularJS creando un filtro e usando il codice di uno qualsiasi degli altri esempi come il seguente:

// 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

Nel tuo controller:

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

O a tuo avviso:

<any ng-expression="object | lengthOfObject"></any>

4
L'OP non ha richiesto una versione di AngularJS. Questa non è una risposta valida alla domanda.
Francisco Hodge, il

10

Il modo più semplice è così

Object.keys(myobject).length

dove myobject è l'oggetto di ciò che vuoi la lunghezza


2
Questo sembra essere solo una ripetizione di questa risposta esistente .
Pang

@Pang ha concordato e non fornisce ulteriori contesti come fanno altre risposte.
Mistico

8

Se non ti interessa supportare Internet Explorer 8 o versioni precedenti, puoi ottenere facilmente il numero di proprietà in un oggetto applicando i due passaggi seguenti:

  1. Eseguire o Object.keys()per ottenere un array che contenga solo i nomi delle proprietà che sono enumerabili o Object.getOwnPropertyNames()se si desidera includere anche i nomi delle proprietà che non sono enumerabili.
  2. Ottieni la .lengthproprietà di quell'array.

Se è necessario farlo più di una volta, è possibile racchiudere questa logica in una funzione:

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

Come usare questa particolare funzione:

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

Vedi anche questo violino per una demo.


8

Utilizzare Object.keys(myObject).lengthper ottenere la lunghezza dell'oggetto / matrice

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

Una variazione su alcuni dei precedenti è:

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

È un modo un po 'più elegante per integrare hasOwnProp.


6

Ecco una versione diversa della risposta di James Cogan. Invece di passare un argomento, basta prototipare la classe Object e rendere il codice più pulito.

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;

esempio jsfiddle: http://jsfiddle.net/qar4j/1/


6
Object.prototype- cattiva idea.
Dziad Borowy,

@tborychowski puoi per favore spiegare perché?
Mohamad,

ecco un articolo: bit.ly/1droWrG . Non sto dicendo che non debba essere fatto, solo che devi conoscere tutte le ripercussioni prima di farlo.
Dziad Borowy,

Se si intende estendere i prototipi incorporati o eseguire il polyfill di una proprietà (es. Patch di scimmia), si prega di farlo correttamente: per compatibilità con il futuro, verificare se la proprietà esiste prima, quindi rendere la proprietà non enumerabile in modo che le proprie chiavi degli oggetti costruiti non sono inquinati. Per i metodi utilizzare metodi effettivi . Il mio consiglio: segui questi esempi che dimostrano come aggiungere un metodo che si comporta il più vicino possibile come i metodi integrati.
user4642212

5

Puoi semplicemente usare Object.keys(obj).lengthqualsiasi oggetto per ottenere la sua lunghezza. Object.keys restituisce un array contenente tutte le chiavi (proprietà) dell'oggetto che possono tornare utili per trovare la lunghezza di quell'oggetto usando la lunghezza dell'array corrispondente. Puoi persino scrivere una funzione per questo. Diventiamo creativi e scriviamo anche un metodo per farlo (insieme a una proprietà getter più comoda):

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
In che cosa differisce dalla risposta di eosynth ?
Peter Mortensen,

È perché mostra come renderlo come una funzione e un metodo di oggetto globale (più orientato agli oggetti e usa una qualche forma di incapsulamento); tuttavia la risposta di aeosynth no.
Mistico

Se si intende estendere i prototipi incorporati o eseguire il polyfill di una proprietà (es. Patch di scimmia), si prega di farlo correttamente: per compatibilità con il futuro, verificare se la proprietà esiste prima, quindi rendere la proprietà non enumerabile in modo che le proprie chiavi degli oggetti costruiti non sono inquinati. Per i metodi utilizzare metodi effettivi . Il mio consiglio: segui questi esempi che dimostrano come aggiungere un metodo che si comporta il più vicino possibile come i metodi integrati.
user4642212

Inoltre, in che modo la scrittura di un metodo è "più efficiente"?
user4642212

5

Puoi sempre fare Object.getOwnPropertyNames(myObject).lengthper ottenere lo stesso risultato che [].lengthdarebbe per un array normale.


1
Object.keys()restituisce un array che contiene solo i nomi delle proprietà enumerabili. Se si desidera un array con TUTTE le proprietà, è necessario utilizzare Object.getOwnPropertyNames()invece. Vedi developer.mozilla.org/it/docs/Web/JavaScript/Reference/…
John Slegers

3
In che cosa differisce dalla risposta di eosynth ?
Peter Mortensen,

4

Possiamo trovare la lunghezza dell'oggetto usando:

Object.values(myObject).length

4

Un po 'tardi al gioco, ma un bel modo per raggiungere questo obiettivo (solo IE9 +) è definire un getter magico sulla proprietà length:

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

E puoi semplicemente usarlo in questo modo:

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

Darei 1.


1
Argomenti contro la modifica del prototipo a parte, personalmente non ho MAI avuto un bug causato da esso e per me è uno dei punti di forza di JavaScript.
MacroMan,

3

Di seguito una versione della risposta di James Coglan in CoffeeScript per coloro che hanno abbandonato JavaScript direttamente :)

Object.size = (obj) ->
  size = 0
  size++ for own key of obj
  size

1
Probabilmente volevi dirlo size++ for own key of obj( own keyessendo lo zucchero sintattico in CoffeeScript). L'uso hasOwnPropertydiretto dall'oggetto è pericoloso, poiché si interrompe quando l'oggetto ha effettivamente tale proprietà.
Konrad Borowski,

2
L'OP non ha richiesto una versione di CoffeeScript, né è etichettato come tale. Questa non è una risposta valida alla domanda.
Francisco Hodge,
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.