Question Comment compter efficacement le nombre de clés / propriétés d'un objet en JavaScript?


Quel est le moyen le plus rapide de compter le nombre de clés / propriétés d'un objet? Est-il possible de faire cela sans itération sur l'objet? c'est-à-dire sans faire

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

(Firefox a fourni une magie __count__ propriété, mais cela a été supprimé quelque part autour de la version 4.)


1192
2017-09-24 08:56


origine


Réponses:


Pour ce faire, dans tout environnement compatible ES5, tel que Nœud, Chrome, IE 9+, FF 4+ ou Safari 5+:

Object.keys(obj).length

1982
2018-02-03 17:47



Vous pouvez utiliser ce code:

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

Vous pouvez ensuite l'utiliser dans les anciens navigateurs:

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

140
2018-04-15 10:48



Si vous utilisez Underscore.js vous pouvez utiliser _.Taille (merci @douwe):
_.size(obj)

Vous pouvez également utiliser _.clés ce qui pourrait être plus clair pour certains:
_.keys(obj).length 

Je recommande fortement Underscore, c'est une bibliothèque étroite pour faire beaucoup de choses de base. Chaque fois que possible, ils correspondent à ECMA5 et se reportent à l'implémentation native.

Sinon, je soutiens la réponse de @ Avi. Je l'ai édité pour ajouter un lien au document MDC qui inclut la méthode keys () que vous pouvez ajouter aux navigateurs non-ECMA5.


126
2018-05-16 15:24



L'implémentation standard de l'objet (ES5.1 Propriétés et méthodes internes de l'objet) ne nécessite pas de Object pour suivre son nombre de clés / propriétés, il ne devrait donc pas y avoir de moyen standard pour déterminer la taille d'un Object sans itération explicite ou implicite sur ses clés.

Voici donc les alternatives les plus couramment utilisées:

1. Object.keys d'ECMAScript ()

Object.keys(obj).length; Fonctionne par intérieurement itérer sur les touches pour calculer un tableau temporaire et renvoie sa longueur.

  • Avantages - Syntaxe lisible et propre. Aucune bibliothèque ou code personnalisé requis sauf un shim si le support natif n'est pas disponible
  • Les inconvénients - Frais généraux de mémoire dus à la création du tableau.

2. Solutions basées sur la bibliothèque

Beaucoup d'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 sans bibliothèque parfait puisque toutes ces méthodes de bibliothèque encapsulent en réalité soit une boucle forcée, soit ES5. Object.keys (natif ou calé).

3. Optimisation d'une boucle for

le partie la plus lente d'une telle boucle est généralement le .hasOwnProperty() appel, à cause de la surcharge de l'appel de fonction. Donc, quand je veux juste le nombre d'entrées d'un objet JSON, je saute simplement le .hasOwnProperty() appelez si je sais qu'aucun code n'a pas et ne s'étendra Object.prototype.

Sinon, votre code pourrait être très légèrement optimisé en faisant k local (var k) et en utilisant l'opérateur prefix-increment (++count) au lieu de postfix.

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

Une autre idée repose sur la mise en cache de la hasOwnProperty méthode:

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

Que ce soit plus rapide ou non sur un environnement donné est une question de benchmarking. Un gain de performance très limité peut être attendu de toute façon.


65
2017-09-24 09:11



Si vous êtes réellement confronté à un problème de performances, je suggère 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é nommée (size?).

Vous devez seulement calculer le nombre initial de propriétés une fois et passer à partir de là. S'il n'y a pas de problème de performance, ne vous embêtez pas. Juste envelopper ce morceau de code dans une fonction getNumberOfProperties(object) et être fait avec.


23
2017-09-24 09:13



Je ne suis au courant d'aucun moyen de le faire, mais pour garder les itérations au minimum, vous pouvez essayer de vérifier l'existence de __count__ et s'il n'existe pas (c'est-à-dire pas Firefox), vous pouvez parcourir l'objet et le définir pour une utilisation ultérieure, par exemple:

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

De cette façon, tout navigateur supportant __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:

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

De cette façon, chaque fois que vous faites référence à myobj.__count__ la fonction se déclenchera et recalculera.


15
2018-01-17 11:15



Comme indiqué par Avi Lin https://stackoverflow.com/a/4889658/1047014

Object.keys(obj).length

fera l'affaire pour toutes les propriétés énumérables sur votre objet, mais pour inclure également les propriétés non énumérables, vous pouvez utiliser le Object.getOwnPropertyNames. Voici la différence:

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

Comme indiqué ici cela 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;)


15
2018-03-30 01:11



Pour itérer sur Avi Flax répondre Object.keys (obj) .length est correct pour un objet qui n'a pas de fonctions liées

Exemple:

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

contre

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

étapes pour éviter cela:

  1. ne mettez pas de fonctions dans un objet que vous voulez compter le nombre de clés dans

  2. utiliser un objet séparé ou créer un nouvel objet spécifiquement pour les fonctions (si vous voulez compter combien de fonctions il y a 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)


12
2018-01-04 09:04