name - windows document javascript




Come contare in modo efficiente il numero di chiavi/proprietà di un oggetto in JavaScript? (13)

Qual è il modo più veloce per contare il numero di chiavi / proprietà di un oggetto? È possibile farlo senza scorrere l'oggetto? cioè senza fare

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

(Firefox ha fornito una proprietà __count__ magica, ma è stata rimossa da qualche parte intorno alla versione 4.)


È possibile utilizzare Object.keys(data).length per trovare la lunghezza dell'oggetto JSON con dati chiave


È possibile utilizzare: Object.keys(objectName).length; & Object.values(objectName).length; Object.keys(objectName).length; & Object.values(objectName).length;


Come affermato da Avi Flax https://.com/a/4889658/1047014

Object.keys(obj).length

farà il trucco per tutte le proprietà enumerabili sul tuo oggetto ma per includere anche le proprietà non enumerabili puoi invece utilizzare Object.getOwnPropertyNames . Ecco la differenza:

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

Come indicato qui, questo ha lo stesso supporto del browser di Object.keys

Tuttavia, nella maggior parte dei casi, potresti non voler includere i non numerabili in questo tipo di operazioni, ma è sempre utile conoscere la differenza;)


Da: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Object.defineProperty (obj, prop, descriptor)

Puoi aggiungerlo a tutti i tuoi oggetti:

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

O un singolo oggetto:

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

Esempio:

var myObj = {};
myObj.name  = "John Doe";
myObj.email = "l[email protected]";
myObj.length; //output: 2

Aggiunto in questo modo, non verrà visualizzato in for..in loop:

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

Produzione:

name:John Doe
email:[email protected]

Nota: non funziona in <IE9 browser.


Ho risolto questo problema costruendo la mia implementazione di un elenco di base che tiene traccia di quanti oggetti sono memorizzati nell'oggetto. È molto semplice. Qualcosa come questo:

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

L'implementazione Object standard ( ES5.1 Object Internal Properties and Methods ) non richiede un Object per tracciare il suo numero di chiavi / proprietà, quindi non ci dovrebbe essere un modo standard per determinare la dimensione di un Object senza iterazione esplicita o implicita sulle sue chiavi .

Quindi ecco le alternative più comunemente usate:

1. Object.keys () di ECMAScript ()

Object.keys(obj).length; Funziona internamente iterando sui tasti per calcolare una matrice temporanea e ne restituisce la lunghezza.

  • Pro : sintassi leggibile e pulita. Nessuna libreria o codice personalizzato richiesto tranne uno shim se il supporto nativo non è disponibile
  • Contro - Sovraccarico della memoria dovuto alla creazione della matrice.

2. Soluzioni basate su libreria

Molti esempi basati su librerie altrove in questo argomento sono utili idiomi nel contesto della loro libreria. Dal punto di vista delle prestazioni, tuttavia, non c'è nulla da guadagnare rispetto a un perfetto codice di non libreria dato che tutti quei metodi di libreria incapsulano effettivamente un oggetto for-loop o ES5 Object.keys (nativo o shimmed).

3. Ottimizzazione di un ciclo for

La parte più lenta di tale ciclo for è generalmente la chiamata .hasOwnProperty() , a causa del sovraccarico di chiamata della funzione. Quindi, quando voglio solo il numero di voci di un oggetto JSON, .hasOwnProperty() chiamata .hasOwnProperty() se so che nessun codice ha fatto né estenderà Object.prototype .

In caso contrario, il codice potrebbe essere leggermente ottimizzato eseguendo k local ( var k ) e utilizzando l'operatore di prefisso-incremento ( ++count ) invece di postfix.

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

Un'altra idea si basa sulla memorizzazione nella cache del metodo hasOwnProperty :

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

Se questo è più veloce o meno in un dato ambiente è una questione di benchmarking. In ogni caso, è possibile prevedere un guadagno prestazionale molto limitato.


Non sono a conoscenza di alcun modo per farlo, tuttavia per mantenere le iterazioni al minimo, si potrebbe provare a verificare l'esistenza di __count__ e se non esiste (cioè non Firefox), si potrebbe scorrere sull'oggetto e definirlo per un uso successivo ad esempio:

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

In questo modo, qualsiasi browser che supporta __count__ lo userebbe e le iterazioni verrebbero eseguite solo per quelle che non lo fanno. Se il conteggio cambia e non puoi farlo, puoi sempre renderlo una funzione:

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

In questo modo ogni volta che fai riferimento a myobj. __count__ la funzione si __count__ e ricalcola.


Per coloro che hanno Ext JS 4 nel loro progetto puoi fare:

Ext.Object.getSize(myobj);

Il vantaggio di questo è che funzionerà su tutti i browser compatibili Ext (incluso IE6-IE8), tuttavia, credo che il tempo di esecuzione non sia migliore di O (n), tuttavia, come con altre soluzioni suggerite.



Per iterare su Avi Flax answer Object.keys (obj) .length è corretto per un oggetto che non ha funzioni ad esso legate

esempio:

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

contro

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

passi per evitare questo:

  1. non mettere le funzioni in un oggetto in cui si desidera contare il numero di chiavi

  2. usa un oggetto separato o crea un nuovo oggetto specificatamente per le funzioni (se vuoi contare quante funzioni ci sono nel file usando Object.keys(obj).length )

anche sì ho usato il modulo _ o underscore da nodejs nel mio esempio

la documentazione può essere trovata qui Underscore.js così come la sua fonte su github e varie altre informazioni

E infine un'implementazione di lodash https://lodash.com/docs#size

_.size(obj)


Se jQuery di cui sopra non funziona, quindi prova

$(Object.Item).length

Se si verifica effettivamente un problema di prestazioni, suggerirei di includere le chiamate che aggiungono / rimuovono le proprietà da / all'oggetto con una funzione che incrementi / decrementi una proprietà denominata (size?) Appropriatamente.

Hai solo bisogno di calcolare il numero iniziale di proprietà una volta e andare avanti da lì. Se non c'è un problema di prestazioni effettive, non preoccuparti. È sufficiente avvolgere quel bit di codice in una funzione getNumberOfProperties(object) e utilizzarlo.


come indicato sopra: Object.keys(obj).length

Ma: dato che ora abbiamo una vera classe Map in ES6, suggest di usarla invece di usare le proprietà di un oggetto.

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






key