Was ist der schnellste Weg, um die Anzahl der Schlüssel / Eigenschaften eines Objekts zu zählen? Ist es möglich, dies zu tun, ohne über das Objekt zu iterieren? dh ohne zu tun
var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;
(Firefox hat eine magische __count__
Eigenschaft bereitgestellt , die jedoch irgendwo um Version 4 entfernt wurde.)
Antworten:
So tun Sie dies in jeder ES5-kompatiblen Umgebung wie Node , Chrome, IE 9+, Firefox 4+ oder Safari 5+:
quelle
Sie könnten diesen Code verwenden:
Dann können Sie dies auch in älteren Browsern verwenden:
quelle
(Object.prototype.hasOwnProperty.call(obj, k))
?hasOwnProperty
erforderlich. Es werden nur Eigenschaften zurückgegeben, die für das Objekt selbst festgelegt wurden.obj.hasOwnProperty(k)
(ich habe das tatsächlich in meinem ursprünglichen Beitrag gemacht, aber später aktualisiert).hasOwnProperty
ist für jedes Objekt verfügbar, da es Teil desObject
Prototyps des Objekts ist. In dem seltenen Fall, dass diese Methode entfernt oder überschrieben wird, erhalten Sie möglicherweise unerwartete Ergebnisse. Wenn SieObject.prototype
es von dort aus aufrufen, wird es etwas robuster. Der Grund für die Verwendungcall
liegt darin, dass Sie die Methodeobj
anstelle des Prototyps aufrufen möchten .Wenn Sie Underscore.js verwenden , können Sie _.size verwenden (danke @douwe):
_.size(obj)
Alternativ können Sie auch _.keys verwenden, die für einige möglicherweise klarer sind:
_.keys(obj).length
Ich kann Underscore nur empfehlen, es ist eine enge Bibliothek für viele grundlegende Dinge. Wann immer möglich, stimmen sie mit ECMA5 überein und verschieben sich auf die native Implementierung.
Ansonsten unterstütze ich die Antwort von @ Avi. Ich habe es bearbeitet, um einen Link zum MDC-Dokument hinzuzufügen, der die keys () -Methode enthält, die Sie Nicht-ECMA5-Browsern hinzufügen können.
quelle
_.keys(obj).length
hat für mich am besten funktioniert, da mein Rückgabeobjekt manchmal eine einfache Zeichenfolge ohne Eigenschaften ist._.size(obj)
gibt mir die Länge der Zeichenfolge zurück, während_.keys(obj).length
0 zurückgibt.Object.keys
intern verwendet. Der Unterstrich kopiert auch jeden Schlüssel in ein Array innerhalb einerfor..in
Schleife, wenn erObject.keys
nicht definiert ist.Die Standardobjektimplementierung ( ES5.1 Objektinterne Eigenschaften und Methoden ) erfordert keine
Object
Verfolgung der Anzahl der Schlüssel / Eigenschaften. Daher sollte es keine Standardmethode geben, um die Größe einer zu bestimmen,Object
ohne explizit oder implizit über ihre Schlüssel zu iterieren.Hier sind die am häufigsten verwendeten Alternativen:
1. Object.keys () von ECMAScript
Object.keys(obj).length;
Funktioniert durch internes Durchlaufen der Schlüssel, um ein temporäres Array zu berechnen und dessen Länge zurückzugeben.2. Bibliotheksbasierte Lösungen
Viele bibliotheksbasierte Beispiele an anderer Stelle in diesem Thema sind nützliche Redewendungen im Kontext ihrer Bibliothek. Unter dem Gesichtspunkt der Leistung gibt es jedoch nichts zu gewinnen im Vergleich zu einem perfekten Code ohne Bibliothek, da alle diese Bibliotheksmethoden entweder eine for-Schleife oder ES5
Object.keys
(nativ oder shimmed) enthalten.3. Optimieren einer for-Schleife
Der langsamste Teil einer solchen for-Schleife ist
.hasOwnProperty()
aufgrund des Funktionsaufrufaufwands im Allgemeinen der Aufruf. Wenn ich also nur die Anzahl der Einträge eines JSON-Objekts möchte, überspringe ich den.hasOwnProperty()
Aufruf, wenn ich weiß, dass kein Code erweitert wurde oder wirdObject.prototype
.Andernfalls könnte Ihr Code geringfügig optimiert werden, indem Sie
k
local (var k
) erstellen und++count
anstelle von postfix den Präfix-Inkrement-Operator ( ) verwenden.Eine andere Idee beruht auf dem Zwischenspeichern der
hasOwnProperty
Methode:Ob dies in einer bestimmten Umgebung schneller ist oder nicht, ist eine Frage des Benchmarking. Es ist ohnehin ein sehr begrenzter Leistungsgewinn zu erwarten.
quelle
var k in myobj
die Leistung gesteigert werden? Soweit ich weiß, deklarieren nur Funktionen neuen Bereich in JavaScript. Sind In-Loops eine Ausnahme von dieser Regel?for (var k in myobj) hasOwn.call(myobj, k) && ++count;
dh die if-Anweisung durch ein einfaches && ersetzen?Object.getOwnPropertyNames(obj).length
; viel einfacher.Wenn Sie tatsächlich auf ein Leistungsproblem stoßen, würde ich empfehlen, die Aufrufe zum Hinzufügen / Entfernen von Eigenschaften zum / vom Objekt mit einer Funktion zu versehen, die auch eine Eigenschaft mit entsprechendem Namen (Größe?) Inkrementiert / dekrementiert.
Sie müssen die anfängliche Anzahl der Eigenschaften nur einmal berechnen und von dort aus fortfahren. Wenn es kein tatsächliches Leistungsproblem gibt, stören Sie sich nicht. Wickeln Sie einfach diesen Code in eine Funktion ein
getNumberOfProperties(object)
und fertig.quelle
Wie von Avi Flax angegeben https://stackoverflow.com/a/4889658/1047014
führt den Trick für alle aufzählbaren Eigenschaften Ihres Objekts aus, aber um auch die nicht aufzählbaren Eigenschaften einzuschließen, können Sie stattdessen die verwenden
Object.getOwnPropertyNames
. Hier ist der Unterschied:Wie hier angegeben, hat dies die gleiche Browserunterstützung wie
Object.keys
In den meisten Fällen möchten Sie die nicht aufzählbaren Werte möglicherweise nicht in diese Art von Operationen einbeziehen, aber es ist immer gut, den Unterschied zu kennen;)
quelle
Object.getOwnPropertyNames
, du warst der einzige hier ...Mir ist keine Möglichkeit bekannt, dies zu tun. Um jedoch die Iterationen auf ein Minimum zu beschränken, können Sie versuchen, die Existenz von zu überprüfen.
__count__
Wenn diese nicht vorhanden sind (dh nicht Firefox), können Sie das Objekt durchlaufen und definieren es für die spätere Verwendung zB:Auf diese Weise würde jeder Browser, der dies unterstützt,
__count__
dies verwenden, und Iterationen würden nur für diejenigen ausgeführt, die dies nicht tun. Wenn sich die Anzahl ändert und Sie dies nicht tun können, können Sie es jederzeit zu einer Funktion machen:Auf diese Weise können Sie jederzeit auf myobj verweisen.
__count__
Die Funktion wird ausgelöst und neu berechnet.quelle
Object.prototype.__count__
in Gecko 1.9.3 entfernt wird: whereswalden.com/2010/04/06/... Zählung -property-of-Objekte-wird-wird-entfernt /Object.__count__
ist weg, und auch gute Befreiung.Um mit Avi Flax zu iterieren, antworten Sie auf Object.keys (obj) .length ist für ein Objekt korrekt, an das keine Funktionen gebunden sind
Beispiel:
gegen
Schritte, um dies zu vermeiden:
Fügen Sie keine Funktionen in ein Objekt ein, in dem Sie die Anzahl der Schlüssel zählen möchten
Verwenden Sie ein separates Objekt oder erstellen Sie ein neues Objekt speziell für Funktionen (wenn Sie zählen möchten, wie viele Funktionen in der Datei enthalten sind
Object.keys(obj).length
)auch ja ich habe das _ oder unterstreichen modul von nodejs in meinem beispiel verwendet
Dokumentation finden Sie hier http://underscorejs.org/ sowie die Quelle auf Github und verschiedene andere Informationen
Und schließlich eine lodash-Implementierung https://lodash.com/docs#size
_.size(obj)
quelle
Array(obj).length
: Es funktioniert nicht. http://jsfiddle.net/Jhy8M/false
, aber ich habe noch keine Dokumentation gefunden , wievar obj = { a: true, b: true }
von dem unterscheiden kannvar obj = {}; obj.a = true; obj.b = true;
oder einfach , wenn eine andere Interpretation / Semantik der W3 wurde von Chrome übernommen.wie oben beantwortet:
Object.keys(obj).length
Aber: Da wir jetzt eine echte Map- Klasse in ES6 haben, würde ich vorschlagen , sie anstelle der Eigenschaften eines Objekts zu verwenden.
quelle
Für diejenigen, die Underscore.js in ihrem Projekt haben, können Sie Folgendes tun:
oder funktionaler Stil:
quelle
Hier sind einige Leistungstests für drei Methoden;
https://jsperf.com/get-the-number-of-keys-in-an-object
Object.keys (). Länge
20.735 Operationen pro Sekunde
Sehr einfach und kompatibel. Läuft schnell, aber teuer, weil es ein neues Array von Schlüsseln erstellt, die dann weggeworfen werden.
Schleife durch die Tasten
15.734 Operationen pro Sekunde
Etwas langsamer, aber bei weitem nicht in der Nähe der Speichernutzung. Daher wahrscheinlich besser, wenn Sie an einer Optimierung für mobile oder andere kleine Maschinen interessiert sind
Karte anstelle von Objekt verwenden
953.839.338 Operationen pro Sekunde
Grundsätzlich verfolgt Map seine eigene Größe, sodass wir nur ein Zahlenfeld zurückgeben. Weit, weit schneller als jede andere Methode. Wenn Sie die Kontrolle über das Objekt haben, konvertieren Sie sie stattdessen in Karten.
quelle
Von: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Sie können es entweder allen Ihren Objekten hinzufügen:
Oder ein einzelnes Objekt:
Beispiel:
Auf diese Weise hinzugefügt, wird es nicht in for..in-Schleifen angezeigt:
Ausgabe:
Hinweis: Es funktioniert nicht in <IE9-Browsern.
quelle
Ich habe dieses Problem gelöst, indem ich meine eigene Implementierung einer Basisliste erstellt habe, in der aufgezeichnet wird, wie viele Elemente im Objekt gespeichert sind. Es ist sehr einfach. Etwas wie das:
quelle
var i = basiclist.count
while(i--){...}
add
ein altes Element ersetzt wird oder obremove
es durch einen nicht vorhandenen Index aufgerufen wird. Es ist auch nicht möglich zu überprüfen, ob die Liste einen bestimmten Index hat, wennundefined
es sich um einen gültigen Elementwert handelt.Sie können
Object.keys(data).length
die Länge des JSON-Objekts mit Schlüsseldaten ermittelnquelle
Für diejenigen, die Ext JS 4 in ihrem Projekt haben, können Sie Folgendes tun:
Dies hat den Vorteil, dass es auf allen Ext-kompatiblen Browsern (einschließlich IE6-IE8) funktioniert. Ich glaube jedoch, dass die Laufzeit nicht besser als O (n) ist, wie bei anderen Lösungsvorschlägen.
quelle
Sie können verwenden:
und
quelle
OP hat nicht angegeben, ob das Objekt eine Knotenliste ist. Wenn dies der Fall ist, können Sie einfach die Längenmethode direkt darauf verwenden. Beispiel:
quelle
Wenn jQuery oben nicht funktioniert, versuchen Sie es
quelle
Object.Item
es nicht existiertIch denke nicht, dass dies möglich ist (zumindest nicht ohne einige Interna). Und ich glaube nicht, dass Sie durch die Optimierung viel gewinnen würden.
quelle
Ich versuche es allen Objekten wie folgt zur Verfügung zu stellen:
quelle
Google Closure hat eine nette Funktion dafür ... goog.object.getCount (obj)
Schauen Sie sich die goog.Object-Dokumentation an
quelle