Frage

Was ist der schnellste Weg, um die Anzahl der Tasten / Eigenschaften eines Objekts zu zählen? Es es möglich, dies zu tun, ohne über das Objekt iterieren? das heißt, ohne dabei

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

(Firefox eine magische __count__ Eigenschaft zu bieten hat, aber das war irgendwo entfernt um Version 4).

War es hilfreich?

Lösung

Um dies zu tun in jeder ES5-kompatible Umgebung , wie Knoten , Chrome, IE 9+, Firefox 4+ oder Safari 5 +:

Object.keys(obj).length

Andere Tipps

Sie können diesen Code verwenden:

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

Dann können Sie diese in älteren Browsern als auch verwenden:

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

Wenn Sie mit Underscore.js Sie verwenden können, _ Größe (dank @douwe):
_.size(obj)

Alternativ können Sie auch _.keys , die für einige klarer sein könnte:
_.keys(obj).length

Ich empfehle Unders, seine eine enge Bibliothek für viele grundlegende Dinge zu tun. Wann immer möglich, sie ECMA5 entsprechen und auf die native Implementierung verschieben.

Ansonsten unterstütze ich @ Avi Antwort. Ich bearbeitete es einen Link zu dem MDC doc hinzuzufügen, die die Schlüssel () -Methode enthält, die Sie nicht-ECMA5 Browser hinzufügen können.

Die Standard-Objektimplementierung ( ES5.1 Objekt Interne Eigenschaften und Methoden ) keine Object erfordert seine Anzahl von Tasten / Eigenschaften zu verfolgen, so sollte es keine Standardmethode sein, die Größe eines Object zu bestimmen, ohne explizit oder implizit Iterieren über die Tasten.

Also hier sind die am häufigsten verwendeten Alternativen:

1. ECMAScript des Object.keys ()

Object.keys(obj).length; Werke von intern über die Tasten Iteration ein temporäres Array zu berechnen und gibt seine Länge.

  • Pros - Lesbare und saubere Syntax. Keine Bibliothek oder benutzerdefinierter Code mit Ausnahme einer Shim erforderlich, wenn die native Unterstützung ist nicht verfügbar
  • Cons - Speicher-Overhead aufgrund der Erstellung des Arrays
  • .

2. Bibliothek-basierte Lösungen

Viele Bibliothek-basierte Beispiele an anderer Stelle in diesem Thema sind nützlich Idiome im Rahmen ihrer Bibliothek. Aus anwendungstechnischer Sicht gibt es jedoch nichts im Vergleich zu gewinnen, um einen perfekten No-Code-Bibliothek, da diese all Bibliotheks-Methoden kapseln tatsächlich entweder ein for-Schleife oder ES5 Object.keys (nativ oder unterfüttert).

3. Optimierung einer for-Schleife

langsamste Teil eines solchen for-Schleife ist im Allgemeinen die .hasOwnProperty() nennen, weil der Funktionsaufruf-Overhead. Also, wenn ich nur die Anzahl der Einträge eines JSON-Objekt möchte ich einfach überspringen die .hasOwnProperty() anrufen, wenn ich weiß, dass kein Code tat noch wird Object.prototype verlängern.

Ansonsten Ihr Code sehr leicht, indem sie k lokal optimiert werden kann (var k) und Präfix-Inkrementoperator (++count) anstelle von Postfix verwendet wird.

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

Eine weitere Idee beruht auf Caching der hasOwnProperty Methode:

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

Ob dies schneller ist oder nicht auf einer bestimmten Umgebung ist eine Frage des Benchmarking. Sehr begrenzter Leistungsgewinn ohnehin zu erwarten ist.

Wenn Sie tatsächlich ein Performance-Problem laufen würde ich vorschlagen, die Anrufe Einwickeln, die Hinzufügen / Entfernen von Eigenschaften zu / von dem Objekt mit einer Funktion, die auch erhöht / dekrementiert eine passenden Namen (Größe?) Eigenschaft.

Sie müssen nur die anfängliche Anzahl von Eigenschaften einmal berechnen und von dort zu bewegen. Wenn es nicht ein tatsächliches Performance-Problem ist, nicht die Mühe. wickelt gerade das Stück Code in einer Funktion getNumberOfProperties(object) und mit ihm getan werden.

Ich bin von keiner Weise bewusst, dies zu tun, aber auf ein Minimum die Iterationen zu halten, Sie versuchen, für die Existenz von __count__ Überprüfung könnten und wenn es nicht vorhanden ist (dh nicht Firefox) dann könnte man iterieren das Objekt und definiert sie zum späteren Verwendung zum Beispiel:

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

Auf diese Weise jeden Browser unterstützt __count__ dass verwenden würde, und Wiederholungen würden nur für diejenigen, durchgeführt werden, die dies nicht tun. Wenn die Zählung ändert und Sie dies nicht tun, könnte man immer es eine Funktion machen:

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

Auf diese Weise jederzeit verweisen Sie myobj.__count__ die Funktion wird ausgelöst, und neu berechnet werden.

Wie bereits erwähnt von Avi Flax https://stackoverflow.com/a/4889658/1047014

Object.keys(obj).length

wird für alle enumerable Eigenschaften auf Ihrem Objekt den Trick tun, sondern auch die nicht-zählbaren Eigenschaften beinhalten können Sie stattdessen die Object.getOwnPropertyNames verwenden. Hier ist der Unterschied:

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

Wie bereits erwähnt hier hat dies die gleiche Browser-Unterstützung als Object.keys

Doch in den meisten Fällen Sie möglicherweise nicht über die nonenumerables in dieser Art von Operationen enthalten sein sollen, aber es ist immer gut, den Unterschied zu kennen;)

auf Avi Flax Antwort Object.keys (obj) .length iterieren ist korrekt für ein Objekt, das Funktionen an sie gebunden haben doesnt

Beispiel:

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

Vergleich

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

Schritte, um dies zu vermeiden:

  1. Sie Funktionen nicht in einem Objekt setzen, dass Sie die Anzahl der Tasten in

  2. zählen mögen
  3. ein separates Objekt verwenden oder ein neues Objekt speziell für Funktionen machen (wenn Sie zählen mögen, wie viele Funktionen gibt es in der Datei mit Object.keys(obj).length ist)

auch ja i verwendet _ oder Untermodul von NodeJS in meinem Beispiel

Dokumentation finden Sie hier: http://underscorejs.org/ sowie seine Quelle auf Github und verschiedene andere Info

Und schließlich eine lodash Implementierung https://lodash.com/docs#size

_.size(obj)

Für diejenigen, die Underscore.js in ihrem Projekt enthalten sind, können Sie tun:

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

oder funktionaler Stil:

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

Von: https: //developer.mozilla. org / en / docs / Web / JavaScript / Reference / Global_Objects / Objekt / DefineProperty

  

Object.defineProperty (obj, stütze, Descriptor)

Sie können entweder fügen Sie alle Ihre Objekte:

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

oder ein einzelnes Objekt:

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

Beispiel:

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

auf diese Weise hinzugefügt, es wird nicht in for..in Schleifen angezeigt:

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

Ausgabe:

name:John Doe
email:leaked@example.com

. Hinweis: es funktioniert nicht in

als beantwortet oben: Object.keys(obj).length

Aber: wie wir haben jetzt eine echte Map Klasse in ES6, würde ich vorschlagen verwenden es statt die Eigenschaften eines Objekts.

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

Wie kann ich dieses Problem gelöst habe, ist meine eigene Implementierung einer Grundliste zu bauen, die eine Aufzeichnung hält, wie viele Elemente in dem Objekt gespeichert. Es ist sehr einfach. So etwas wie folgt aus:

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

Für diejenigen, die Ext JS 4 in ihrem Projekt haben Sie tun können:

Ext.Object.getSize(myobj);

Der Vorteil hierbei ist, dass es auf allen Ext kompatibele Browser wird (IE6-IE8 enthalten), aber ich glaube, die Laufzeit ist nicht besser als O (n), obwohl, wie bei anderen vorgeschlagenen Lösungen.

Sie können Object.keys(data).length verwenden die Länge von JSON-Objekt mit Schlüsseldaten zu finden

Wenn jQuery oben nicht funktioniert, dann versuchen

$(Object.Item).length

OP hat nicht angegeben, ob das Objekt ein nodeList ist, wenn es dann können Sie einfach Länge Methode direkt darauf. Beispiel:

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

Ich glaube nicht, das möglich ist (zumindest nicht ohne einige Einbauten verwendet wird). Und ich glaube nicht, dass Sie viel gewinnen würde dies durch die Optimierung.

Ich versuche, es alle wie dieses Objekt zur Verfügung zu stellen:

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

Google Closure hat eine nette Funktion für diese ... goog.object.getCount (obj)

sehen goog.Object Dokumentation

Sie können mit:  Object.keys(objectName).length; & Object.values(objectName).length;

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top