Quelle est la manière la plus rapide de compter le nombre de clés / propriétés d'un objet? Est-il possible de le faire sans itérer sur l'objet? c'est à dire sans faire
var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;
(Firefox a fourni une __count__
propriété magique , mais cela a été supprimé quelque part autour de la version 4.)
Réponses:
Pour ce faire, dans n'importe quel environnement compatible ES5 , tel que Node , Chrome, IE 9+, Firefox 4+ ou Safari 5+:
la source
Vous pouvez utiliser ce code:
Ensuite, vous pouvez également l'utiliser dans les anciens navigateurs:
la source
(Object.prototype.hasOwnProperty.call(obj, k))
?hasOwnProperty
est nécessaire. Il renvoie uniquement les propriétés définies sur l'objet lui-même.obj.hasOwnProperty(k)
(je l'ai fait dans mon article d'origine, mais je l'ai mis à jour plus tard).hasOwnProperty
est disponible sur chaque objet car il fait partie duObject
prototype de, mais dans le cas rare où cette méthode serait supprimée ou remplacée, vous pourriez obtenir des résultats inattendus. En l'appelant depuis,Object.prototype
il le rend peu plus robuste. La raison de l'utilisationcall
est que vous souhaitez invoquer la méthode auobj
lieu du prototype.Si vous utilisez Underscore.js, vous pouvez utiliser _.size (merci @douwe):
_.size(obj)
Alternativement, vous pouvez également utiliser _.keys qui pourrait être plus clair pour certains:
_.keys(obj).length
Je recommande fortement Underscore, sa bibliothèque serrée pour faire beaucoup de choses de base. Dans la mesure du possible, ils correspondent à ECMA5 et s'en remettent à l'implémentation native.
Sinon, je soutiens la réponse de @ Avi. Je l'ai édité pour ajouter un lien vers le document MDC qui inclut la méthode keys () que vous pouvez ajouter aux navigateurs non ECMA5.
la source
_.keys(obj).length
a fonctionné le mieux pour moi, car mon objet de retour est parfois une chaîne simple sans propriétés._.size(obj)
me rend la longueur de la chaîne, tandis que_.keys(obj).length
renvoie 0.Object.keys
interne. Underscore copie également chaque clé dans un tableau à l'intérieur d'unefor..in
boucle si elleObject.keys
n'est pas définie.L'implémentation d'objet standard ( propriétés et méthodes internes de l'objet ES5.1 ) ne nécessite pas
Object
de suivi de son nombre de clés / propriétés, il ne devrait donc pas y avoir de méthode standard pour déterminer la taille d'unObject
sans itération explicite ou implicite sur ses clés.Voici donc les alternatives les plus utilisées:
1. Object.keys d'ECMAScript ()
Object.keys(obj).length;
Fonctionne en itérant en interne sur les clés pour calculer un tableau temporaire et renvoie sa longueur.2. Solutions basées sur la bibliothèque
De nombreux exemples basés sur des bibliothèques ailleurs dans cette rubrique sont des idiomes utiles dans le contexte de leur bibliothèque. Du point de vue des performances, cependant, il n'y a rien à gagner par rapport à un code parfait sans bibliothèque, car toutes ces méthodes de bibliothèque encapsulent en fait une boucle for ou ES5
Object.keys
For (native ou shimmed).3. Optimiser une boucle for
La partie la plus lente d'une telle boucle for est généralement l'
.hasOwnProperty()
appel, en raison de la surcharge d'appel de la fonction. Donc, quand je veux juste le nombre d'entrées d'un objet JSON, je saute juste l'.hasOwnProperty()
appel si je sais qu'aucun code n'a fait ni ne s'étendraObject.prototype
.Sinon, votre code pourrait être très légèrement optimisé en rendant
k
local (var k
) et en utilisant l'opérateur prefix-increment (++count
) au lieu de postfix.Une autre idée repose sur la mise en cache de la
hasOwnProperty
méthode:Que ce soit plus rapide ou non dans un environnement donné est une question de benchmarking. Un gain de performances très limité peut être attendu de toute façon.
la source
var k in myobj
augmenterait les performances? Pour autant que je sache, seules les fonctions déclarent une nouvelle portée en JavaScript. Les boucles entrantes sont-elles une exception à cette règle?for (var k in myobj) hasOwn.call(myobj, k) && ++count;
c'est-à-dire remplacer l'instruction if par un simple &&?Object.getOwnPropertyNames(obj).length
:; beaucoup plus simple.Si vous rencontrez réellement un problème de performances, je suggérerais d'encapsuler les appels qui ajoutent / suppriment des propriétés à / de l'objet avec une fonction qui incrémente / décrémente également une propriété (taille?) Correctement nommée.
Vous n'avez qu'à calculer une fois le nombre initial de propriétés et à partir de là. S'il n'y a pas de réel problème de performances, ne vous embêtez pas. Enveloppez simplement ce morceau de code dans une fonction
getNumberOfProperties(object)
et terminez avec.la source
Comme indiqué par Avi Flax https://stackoverflow.com/a/4889658/1047014
fera l'affaire pour toutes les propriétés énumérables de votre objet, mais pour inclure également les propriétés non énumérables, vous pouvez utiliser à la place le
Object.getOwnPropertyNames
. Voici la différence:Comme indiqué ici, il a le même support de navigateur que
Object.keys
Cependant, dans la plupart des cas, vous ne voudrez peut-être pas inclure les non-énumérables dans ce type d'opérations, mais il est toujours bon de connaître la différence;)
la source
Object.getOwnPropertyNames
, vous étiez le seul ici ...Je ne connais aucun moyen de le faire, mais pour garder les itérations au minimum, vous pouvez essayer de vérifier l'existence de
__count__
et si elle n'existe pas (c'est-à-dire pas Firefox), vous pouvez parcourir l''objet et définir pour une utilisation ultérieure, par exemple:De cette façon, tout navigateur prenant en charge
__count__
utiliserait cela, et les itérations ne seraient effectuées que pour ceux qui ne le font pas. Si le nombre change et que vous ne pouvez pas le faire, vous pouvez toujours en faire une fonction:De cette façon, chaque fois que vous faites référence à myobj.
__count__
la fonction se déclenche et recalcule.la source
Object.prototype.__count__
cours de suppression dans Gecko 1.9.3: whereswalden.com/2010/04/06/... nombre -property-de-objets est-être grattées /Object.__count__
est parti, et bon débarras aussi.Pour itérer sur Avi Flax, répondez Object.keys (obj) .length est correct pour un objet qui n'a pas de fonctions liées à lui
exemple:
contre
étapes pour éviter cela:
ne placez pas de fonctions dans un objet dans lequel vous souhaitez compter le nombre de clés
utiliser un objet séparé ou créer un nouvel objet spécifiquement pour les fonctions (si vous voulez compter le nombre de fonctions dans le fichier en utilisant
Object.keys(obj).length
)aussi oui j'ai utilisé le module _ ou underscore de nodejs dans mon exemple
la documentation peut être trouvée ici http://underscorejs.org/ ainsi que sa source sur github et diverses autres informations
Et enfin une implémentation lodash https://lodash.com/docs#size
_.size(obj)
la source
Array(obj).length
: Cela ne fonctionne pas. http://jsfiddle.net/Jhy8M/false
, bien que je n'ai pas encore trouvé de documentation sur la façon dontvar obj = { a: true, b: true }
peut différervar obj = {}; obj.a = true; obj.b = true;
ou simplement si une interprétation / sémantique différente du W3 a été adopté par Chrome.comme répondu ci-dessus:
Object.keys(obj).length
Mais: comme nous avons maintenant une vraie classe Map dans ES6, je suggère de l'utiliser au lieu d'utiliser les propriétés d'un objet.
la source
Pour ceux qui ont Underscore.js inclus dans leur projet, vous pouvez faire:
ou style fonctionnel:
la source
Voici quelques tests de performances pour trois méthodes;
https://jsperf.com/get-the-number-of-keys-in-an-object
Object.keys (). Length
20 735 opérations par seconde
Très simple et compatible. Fonctionne rapidement mais cher car il crée un nouveau tableau de clés, qui est ensuite jeté.
parcourir les clés
15 734 opérations par seconde
Légèrement plus lent, mais loin de l'utilisation de la mémoire, donc probablement mieux si vous êtes intéressé par l'optimisation pour les machines mobiles ou autres petites
Utiliser la carte au lieu de l'objet
953 839 338 opérations par seconde
Fondamentalement, Map suit sa propre taille, nous ne faisons que renvoyer un champ numérique. Loin, bien plus vite que toute autre méthode. Si vous avez le contrôle de l'objet, convertissez-les à la place en cartes.
la source
De: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Vous pouvez soit l'ajouter à tous vos objets:
Ou un seul objet:
Exemple:
Ajouté de cette façon, il ne sera pas affiché dans les boucles for..in:
Production:
Remarque: cela ne fonctionne pas dans les navigateurs <IE9.
la source
La façon dont j'ai résolu ce problème consiste à créer ma propre implémentation d'une liste de base qui conserve un enregistrement du nombre d'éléments stockés dans l'objet. C'est très simple. Quelque chose comme ça:
la source
var i = basiclist.count
while(i--){...}
add
remplace un ancien élément ou siremove
est appelé avec un index inexistant. De plus, il n'est pas possible de vérifier si la liste a un index donné s'ilundefined
s'agit d'une valeur d'élément valide.Vous pouvez utiliser
Object.keys(data).length
pour trouver la longueur d'un objet JSON contenant des données clésla source
Pour ceux qui ont Ext JS 4 dans leur projet, vous pouvez faire:
L'avantage de cela est qu'il fonctionnera sur tous les navigateurs compatibles Ext (IE6-IE8 inclus), cependant, je pense que le temps d'exécution n'est pas meilleur que O (n), comme avec les autres solutions suggérées.
la source
Vous pouvez utiliser:
et
la source
OP n'a pas spécifié si l'objet est un nodeList, si c'est le cas, vous pouvez simplement utiliser la méthode de longueur directement dessus. Exemple:
la source
Si jQuery ci-dessus ne fonctionne pas, essayez
la source
Object.Item
n'existe pasJe ne pense pas que ce soit possible (du moins pas sans utiliser des internes). Et je ne pense pas que vous gagneriez beaucoup en optimisant cela.
la source
J'essaie de le rendre disponible à tous les objets comme celui-ci:
la source
Google Closure a une fonction intéressante pour cela ... goog.object.getCount (obj)
regardez goog.Object Documentation
la source