Cum să eficient conta numărul de chei/de proprietăți a unui obiect în JavaScript?

Ce's cel mai rapid mod de a conta numărul de chei/de proprietăți a unui obiect? Este posibil să facă acest lucru fără iterarea peste obiect? adică, fără a face

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

(Firefox făcut oferi o magiecount proprietate, dar acest lucru a fost scos pe undeva pe versiunea 4.)

Comentarii la întrebare (3)
Soluția

Pentru a face acest lucru în orice ES5-compatibil mediu, precum Nod, Chrome, IE 9+, Firefox 4+, Safari 5+:

Object.keys(obj).length
Comentarii (25)

Ai putea folosi acest cod:

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

Apoi puteți folosi acest lucru în browsere mai vechi precum:

var len = Object.keys(obj).length;
Comentarii (12)

Dacă utilizați Underscore.js puteți utiliza _.size (multumesc @douwe): _.dimensiune(obj)

Alternativ, puteți utiliza, de asemenea, _.chei care ar putea fi mai clar pentru unii: _.cheile(obj).lungime

Am foarte recomanda Subliniere, sa o strâns bibliotecă pentru a face o mulțime de lucruri de bază. Ori de câte ori este posibil se potrivesc ECMA5 și amâna la punerea în aplicare nativ.

În caz contrar, susțin @Avi's a răspunde. Am editat pentru a adăuga un link la MDC doc care include cheile() metodă, puteți adăuga la non-ECMA5 browsere.

Comentarii (7)

Standard Obiect de punere în aplicare (ES5.1 Obiect Intern Proprietăți și Metode) nu are nevoie de un "Obiect" pentru a urmări numărul de chei/proprietăți, deci nu ar fi nici o modalitate standard de a determina dimensiunea de un "Obiect" fără explicit sau implicit iterarea peste cheile sale.

Deci, aici sunt cele mai frecvent utilizate alternative:

1. ECMAScript's Obiect.tastele()

`Obiect.cheile(obj).lungime; Lucrări de intern iterarea peste cheile pentru a calcula o temporară matrice și returnează lungimea sa.

  • Pro - ușor de Citit și curat sintaxă. Nici o bibliotecă sau un cod personalizat necesară, cu excepția un shim dacă suport nativ este indisponibil
  • Contra - Memorie aeriene ca urmare a creării de matrice.

2. Biblioteca soluții bazate pe

Multe bibliotecă pe bază de exemple în altă parte în acest subiect sunt utile expresii în contextul lor bibliotecă. Dintr-un punct de vedere performanta, cu toate acestea, nu este nimic de a câștiga în comparație cu o perfectă nu-bibliotecă cod de toți cei biblioteca metodele de fapt îngloba fie un pentru buclă sau ES5 Obiect.chei (nativ sau shimmed).

3. Optimizarea o pentru buclă

La lent parte de o astfel de buclă este în general .hasOwnProperty() apel, pentru că de apelul funcției deasupra capului. Așa că atunci când vreau doar numărul de intrări de un obiect JSON, doar sari peste .hasOwnProperty () sun dacă am ști că nici un cod nu se va extindeObiect.prototip`.

În caz contrar, codul ar putea fi foarte ușor optimizat prin a face " k " locale (var k) și prin utilizarea prefix-operatorul de incrementare (++conta) în loc de postfix.

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

O altă idee se bazează pe cache hasOwnProperty metoda:

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

Dacă acest lucru este mai rapid sau nu pe un anumit mediu este o chestiune de benchmarking. Foarte limitate de creștere a performanței poate fi de așteptat oricum.

Comentarii (2)

Dacă sunt, de fapt rula într-o problemă de performanță aș sugera ambalaj apelurile care se adăuga/elimina proprietăți de la/la obiect cu o funcție care, de asemenea, creșteri/diminuări de un nume adecvat (dimensiune?) proprietate.

Ai nevoie doar pentru a calcula numărul inițial de proprietăți odată și pentru a muta de acolo. Dacă nu există't o reală problemă de performanță, don't deranjez. Înfășurați doar că pic de cod într-o funcție `getNumberOfProperties(obiect) și să fie făcut cu ea.

Comentarii (6)

Am'm nu are cunoștință de nicio modalitate de a face acest lucru, cu toate acestea, pentru a menține iterații la un nivel minim, ai putea încerca de verificare pentru existenta __count__ și dacă nu't există (de exemplu, nu Firefox), atunci ai putea repeta peste obiect și-l definească pentru o utilizare ulterioară, de exemplu:

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

În acest fel în orice browser-ul de sprijin __count__ ar folosi asta, și iterații ar fi efectuate numai pentru cei care don't. În cazul în care numărul modificările și puteți't face acest lucru, ai putea face întotdeauna o funcție:

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

În acest fel, oricand ai referință myobj.__conta__ funcția va foc și se recalculează.

Comentarii (4)

După cum sa afirmat de Avi In https://stackoverflow.com/a/4889658/1047014

Object.keys(obj).length

va face truc pentru toate nenumărate proprietăți pe obiect, ci să includă, de asemenea, non-nenumărate proprietăți puteți folosi în loc de Obiect.getOwnPropertyNames. Aici's diferența:

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

După cum a afirmat aici acest lucru are același sprijin browser-ul ca Obiect.tastele

Cu toate acestea, în cele mai multe cazuri, s-ar putea să nu doriți să includă nonenumerables în acest tip de operațiuni, dar's întotdeauna bine să știți diferența ;)

Comentarii (0)

Pentru a repeta pe un Avi In răspundă la Obiect.cheile(obj).lungimea este corect pentru un obiect care nu are funcții legate de aceasta

exemplu:

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

versus

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

pași pentru a evita acest lucru:

  1. nu pune funcții într-un obiect pe care doriți să conta numărul de chei în

  2. utilizarea separată de obiect sau de a face un obiect nou special pentru funcții (dacă doriți să conta cât de multe funcții sunt în fișier folosind Obiect.cheile(obj).lungimea)

de asemenea, da am folosit _ sau subliniere modul de nodejs în exemplul meu

documentație pot fi găsite aici http://underscorejs.org/ precum și ca sursă pe github și diverse alte informatii

Și în cele din urmă un lodash punerea în aplicare https://lodash.com/docs#size

_.dimensiune(obj)

Comentarii (4)

ca raspuns mai sus: Obiect.cheile(obj).lungime

Dar: ca avem acum o real Harta clasă în ES6, am ar arată să-l folosească în loc de a folosi proprietățile unui obiect.

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

Pentru cei care au Underscore.js incluse în proiectul lor le puteți face:

_({a:'', b:''}).size() // => 2

sau stil funcțional:

_.size({a:'', b:''}) // => 2
Comentarii (0)

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

Obiect.defineProperty(obj, prop, descriptor)

Puteți fie să adăugați-l la toate obiectele:

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

Sau un singur obiect:

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

Exemplu:

var myObj = {};
myObj.name  = "John Doe";
myObj.email = "leaked@example.com";
myObj.length; //output: 2

A adăugat că va avea't fi afișate în for..în bucle:

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

Ieșire:

name:John Doe
email:leaked@example.com

Notă: nu funcționează în < IE9 browsere.

Comentarii (0)

Cum am'am rezolvat această problemă este de a construi propriul meu punerea în aplicare de o listă de bază care ține o evidență a cât de multe elemente sunt stocate în obiect. Este foarte simplu. Ceva de genul asta:

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];
   }
}
Comentarii (9)

Puteți folosi Obiect.cheile(de date).lungime` pentru a găsi lungimea de obiect JSON având datele-cheie

Comentarii (0)

Pentru cei care au Ext JS 4 în proiectul lor le puteți face:

Ext.Object.getSize(myobj);

Avantajul acestui fapt este că-l'll lucra pe toate Ext browsere compatibile (IE6-IE8 inclus), cu toate acestea, cred că timpul de funcționare este mai bună decât O(n), deși, ca și cu alte soluții sugerate.

Comentarii (0)

OP n't specifica dacă obiectul este un nodeList, dacă este, atunci puteți folosi doar lungime metoda pe ea direct. Exemplu:

buttons = document.querySelectorAll('[id=button)) {
console.log('Found ' + buttons.length + ' on the screen'); 
Comentarii (0)

Dacă jQuery de mai sus nu funcționează, apoi încercați

$(Object.Item).length
Comentarii (1)

Aici sunt unele teste de performanță pentru trei metode;

https://jsperf.com/get-the-number-of-keys-in-an-object

Obiect.tastele().lungime

20,735 operații pe secundă

Foarte simplu și compatibile. Se execută rapid but scumpe pentru că se creează o nouă serie de chei, care apoi este aruncat.

returnare Obiect.cheile(objectToRead).lungime;

bucla prin chei

15,734 operații pe secundă

să size=0; pentru(fie k în objectToRead) { dimensiunea++ } reveni dimensiune;

Ușor mai lent, dar nicăieri în apropiere de utilizare de memorie, deci probabil mai bine dacă te - 're interesat în optimizarea pentru mobil sau alte masini mici

Folosind Harta în loc de Obiect

953,839,338 operații pe secundă

reveni mapToRead.dimensiune;

Practic, Harta piese propria sa dimensiune atât de ne're întorcându-se doar o serie de teren. Mult, mult mai repede decât orice altă metodă. Dacă aveți de control al obiectului, de a le converti la hărți în loc.

Comentarii (0)

Puteți utiliza:

Object.keys(objectName).length; 

și

Object.values(objectName).length;
Comentarii (0)

Am încercat să-l facă disponibil pentru toți obiect de genul asta:

Object.defineProperty(Object.prototype, "length", {
get() {
    if (!Object.keys) {
        Object.keys = function (obj) {
            var keys = [],k;
            for (k in obj) {
                if (Object.prototype.hasOwnProperty.call(obj, k)) {
                    keys.push(k);
                }
            }
            return keys;
        };
    }
    return Object.keys(this).length;
},});

console.log({"Name":"Joe","Age":26}.length) //returns 2
Comentarii (0)

Eu nu't cred că acest lucru este posibil (cel puțin nu fără a utiliza unele interne). Și eu nu't cred că ar câștiga mult prin optimizarea acest lucru.

Comentarii (1)