528 Stimmen

Ist das Objekt leer?

Wie kann man am schnellsten prüfen, ob ein Objekt leer ist oder nicht?

Gibt es einen schnelleren und besseren Weg als diesen?

function count_obj(obj){
    var i = 0;
    for(var key in obj){
        ++i;
    }

    return i;
}

6 Stimmen

Möchten Sie die Eigenschaften zählen (das ist es, was der Code tut) oder nur testen, ob das Objekt leer ist oder nicht (das ist in Ihrer Frage angegeben)?

2 Stimmen

Nur als Empfehlung von Bibliotheken, die dazu in der Lage sind is.js y lodash

0 Stimmen

Für derartige Dienstprogramme empfiehlt es sich, einige Bibliotheken zu verwenden. Sie könnten lodash verwenden und etwas wie _.isEmpty(_.keys(yourObject)) . Und ich glaube, Sie können jetzt diese beiden Methoden einzeln importieren, und nicht die gesamte Lodash-Bibliothek.

646voto

Jakob Punkte 23652

Für ECMAScript5 (das allerdings noch nicht von allen Browsern unterstützt wird), können Sie verwenden:

Object.keys(obj).length === 0

124 Stimmen

Eine angemessenere ES5-Lösung wäre Object.getOwnPropertyNames(obj).length == 0 というのも Object.keys erhält nur die aufzählbar Eigenschaften. In ES5 haben wir die Möglichkeit, Eigenschaftsattribute zu definieren, wir könnten ein Objekt mit nicht aufzählbaren Eigenschaften haben und Object.keys wird einfach ein leeres Array zurückgeben... Object.getOwnPropertyNames gibt ein Array zurück, das todos die eigenen Eigenschaften eines Objekts, auch wenn sie nicht aufzählbar sind.

10 Stimmen

@CMS getOwnPropertyNames es empfohlen von Crockford . Ihm zufolge wurde diese Methode speziell für Caja (und andere sichere Frameworks, nehme ich an) in die Sprache eingeführt. Es besteht also die Möglichkeit, dass diese Methode in bestimmten Umgebungen nicht verfügbar ist oder sein wird.

2 Stimmen

Dies ist die ECMAScript5-Kompatibilitätstabelle: kangax.github.io/es5-compat-table

463voto

Sean Vieira Punkte 147654

Ich gehe davon aus, dass durch leer Sie meinen "hat keine eigenen Eigenschaften".

// Speed up calls to hasOwnProperty
var hasOwnProperty = Object.prototype.hasOwnProperty;

function isEmpty(obj) {

    // null and undefined are "empty"
    if (obj == null) return true;

    // Assume if it has a length property with a non-zero value
    // that that property is correct.
    if (obj.length > 0)    return false;
    if (obj.length === 0)  return true;

    // If it isn't an object at this point
    // it is empty, but it can't be anything *but* empty
    // Is it empty?  Depends on your application.
    if (typeof obj !== "object") return true;

    // Otherwise, does it have any properties of its own?
    // Note that this doesn't handle
    // toString and valueOf enumeration bugs in IE < 9
    for (var key in obj) {
        if (hasOwnProperty.call(obj, key)) return false;
    }

    return true;
}

Beispiele:

isEmpty(""), // true
isEmpty(33), // true (arguably could be a TypeError)
isEmpty([]), // true
isEmpty({}), // true
isEmpty({length: 0, custom_property: []}), // true

isEmpty("Hello"), // false
isEmpty([1,2,3]), // false
isEmpty({test: 1}), // false
isEmpty({length: 3, custom_property: [1,2,3]}) // false

Wenn Sie nur Folgendes bearbeiten müssen ECMAScript5-Browser können Sie verwenden Object.getOwnPropertyNames anstelle der hasOwnProperty Schleife:

if (Object.getOwnPropertyNames(obj).length > 0) return false;

Dadurch wird sichergestellt, dass selbst wenn das Objekt nur nicht aufzählbare Eigenschaften hat isEmpty erhalten Sie trotzdem die richtigen Ergebnisse.

5 Stimmen

@SeanVieira is_empty({length: 0, custom_property: []}) gibt false zurück. Ich bin mir nicht sicher, wie der Code funktionieren soll, aber ich würde erwarten, dass er korrekt ist, wenn Sie Folgendes hinzufügen: if (obj.length === 0) return true; after if (obj.length && obj.length > 0) return false; es wäre korrekt

2 Stimmen

@pgreen2 - gut gefangen! Ich habe das Beispiel aktualisiert, um eine explizite Prüfung auf 0 einzuschließen - danke für die Hilfe bei der Verbesserung der Antwort!

0 Stimmen

JSLint beschwert sich hasOwnProperty is a really bad name . Das behebt es {}.hasOwnProperty.call(obj, key) . Impressum ici

226voto

johndodo Punkte 15249

EDIT : Beachten Sie, dass Sie wahrscheinlich ES5-Lösung stattdessen, da die ES5-Unterstützung weit verbreitet in diesen Tagen. Es funktioniert immer noch für jQuery aber.


Ein einfacher und browserübergreifender Weg ist die Verwendung von jQuery.isEmptyObject :

if ($.isEmptyObject(obj))
{
    // do something
}

Mehr: http://api.jquery.com/jQuery.isEmptyObject/

Sie benötigen jedoch Jquery.

55 Stimmen

Ich finde es amüsant, dass die jQuery-Option diejenige ist, die "vorbildlich und einer zusätzlichen Prämie würdig" ist, über eine native ES5-Lösung . Diese Antwort ist in einigen Fällen immer noch nützlich, nehme ich an.

2 Stimmen

Die ES5-Lösung wird (noch) nicht von allen Browsern unterstützt (zumindest AFAIK), daher ist diese Lösung sinnvoll, wenn Sie bereits jQuery verwenden (was bei vielen Websites der Fall ist). Außerdem ist jQuery ein bisschen effizienter als Jakobs Lösung (nicht, dass es in den meisten Fällen viel ausmacht), da es nicht das ganze Objekt durchläuft, bevor es die Länge berechnet - es gibt false, sobald ein Schlüssel gefunden wird .

0 Stimmen

Dies funktioniert nicht im IE8. Siehe stackoverflow.com/questions/679915/

101voto

Brad Koch Punkte 17657

Unterstrich y lodash haben jeweils eine praktische isEmpty() Funktion, wenn es Ihnen nichts ausmacht, eine zusätzliche Bibliothek hinzuzufügen.

_.isEmpty({});

23 Stimmen

Oder für Leute, die bereits einen Unterstrich eingefügt haben ;)

6 Stimmen

Späte Bemerkung: für 2016 können Sie nur lodash verwenden isEmpty (Sie müssen nicht die gesamte Lodash importieren, Sie können jetzt nur eine Methode daraus importieren, sie wurde in mehrere Mikropakete in npm aufgeteilt).

0 Stimmen

Ja, oder Sie könnten importieren node_modules/* und ignorieren Sie jede Abhängigkeit von einem Plugin </sarcasm>

69voto

davidhadas Punkte 2233

Lassen Sie uns dieses Baby zu Bett; getestet unter Node, Chrome, Firefox und IE 9, wird es offensichtlich, dass für die meisten Anwendungsfälle:

  • (für...in...) ist die schnellste Option, die Sie verwenden können!
  • Object.keys(obj).length ist bei leeren Objekten 10 Mal langsamer
  • JSON.stringify(obj).length ist immer am langsamsten (nicht überraschend)
  • Object.getOwnPropertyNames(obj).length dauert länger als Object.keys(obj).length kann auf manchen Systemen viel länger sein.

Unterm Strich Leistung, verwenden:

function isEmpty(obj) { 
   for (var x in obj) { return false; }
   return true;
}

o

function isEmpty(obj) {
   for (var x in obj) { if (obj.hasOwnProperty(x))  return false; }
   return true;
}

Ergebnisse unter Node:

  • erstes Ergebnis: return (Object.keys(obj).length === 0)
  • zweites Ergebnis: for (var x in obj) { return false; }...
  • drittes Ergebnis: for (var x in obj) { if (obj.hasOwnProperty(x)) return false; }...
  • viertes Ergebnis: return ('{}' === JSON.stringify(obj))

Prüfung auf Objekt mit 0 Schlüsseln 0.00018 0.000015 0.000015 0.000324

Prüfung auf Objekt mit 1 Schlüssel 0.000346 0.000458 0.000577 0.000657

Prüfung auf Objekt mit 2 Schlüsseln 0.000375 0.00046 0.000565 0.000773

Prüfung auf Objekt mit 3 Schlüsseln 0.000406 0.000476 0.000577 0.000904

Prüfung auf Objekt mit 4 Tasten 0.000435 0.000487 0.000589 0.001031

Prüfung auf Objekt mit 5 Schlüsseln 0.000465 0.000501 0.000604 0.001148

Prüfung auf Objekt mit 6 Tasten 0.000492 0.000511 0.000618 0.001269

Prüfung auf Objekt mit 7 Tasten 0.000528 0.000527 0.000637 0.00138

Prüfung auf Objekt mit 8 Tasten 0.000565 0.000538 0.000647 0.00159

Prüfung auf Objekt mit 100 Schlüsseln 0.003718 0.00243 0.002535 0.01381

Testen auf Objekt mit 1000 Schlüsseln 0.0337 0.0193 0.0194 0.1337

Wenn Ihr typischer Anwendungsfall ein nicht leeres Objekt mit wenigen Schlüsseln testet und Sie selten leere Objekte oder Objekte mit 10 oder mehr Schlüsseln testen, sollten Sie die Option Object.keys(obj).length in Betracht ziehen. - Andernfalls sollten Sie die allgemeinere (for... in...) Implementierung verwenden.

Beachten Sie, dass Firefox scheinen eine schnellere Unterstützung für Object.keys(obj).length und Object.getOwnPropertyNames(obj).length, so dass es eine bessere Wahl für jede nicht leere Objekt, aber immer noch, wenn es darum geht, leere Objekte, die (for...in...) ist einfach 10 mal schneller.

Meine 2 Cents ist, dass Object.keys(obj).length eine schlechte Idee ist, da es ein Objekt von Schlüsseln erstellt, nur um zu zählen, wie viele Schlüssel darin sind, dann zerstört es! Um dieses Objekt zu erstellen, muss er die Schlüssel in einer Schleife durchlaufen... warum also diese und nicht die Option (for... in...) verwenden :)

var a = {};

function timeit(func,count) {
   if (!count) count = 100000;
   var start = Date.now();
   for (i=0;i<count;i++) func();
   var end = Date.now();
   var duration = end - start;
   console.log(duration/count)
}

function isEmpty1() {
    return (Object.keys(a).length === 0)
}
function isEmpty2() {
    for (x in a) { return false; }
    return true;
}
function isEmpty3() {
    for (x in a) { if (a.hasOwnProperty(x))  return false; }
    return true;
}
function isEmpty4() {
    return ('{}' === JSON.stringify(a))
}

for (var j=0;j<10;j++) {
   a = {}
   for (var i=0;i<j;i++) a[i] = i;
   console.log('Testing for Object with '+Object.keys(a).length+' keys')
   timeit(isEmpty1);
   timeit(isEmpty2);
   timeit(isEmpty3);
   timeit(isEmpty4);
}

a = {}
for (var i=0;i<100;i++) a[i] = i;
console.log('Testing for Object with '+Object.keys(a).length+' keys')
timeit(isEmpty1);
timeit(isEmpty2);
timeit(isEmpty3);
timeit(isEmpty4, 10000);

a = {}
for (var i=0;i<1000;i++) a[i] = i;
console.log('Testing for Object with '+Object.keys(a).length+' keys')
timeit(isEmpty1,10000);
timeit(isEmpty2,10000);
timeit(isEmpty3,10000);
timeit(isEmpty4,10000);

1 Stimmen

for (x in a) { return false; } kann eine blocklose Einzelanweisung sein for Erklärung. Das heißt, Sie können eine Stapelblockoperation speichern, indem Sie die {} . Eine Art nutzlose Information. Könnte sich aber bei Ihrer 6-stelligen Zeitmessungsgenauigkeit bemerkbar machen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X