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

Quelle est la façon 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 propriété magique __count__ , mais celle-ci a été retirée quelque part autour de la version 4.)

1232
demandé sur Luc125 2008-09-24 12:56:21
la source

19 ответов

pour le faire dans n'importe quel environnement compatible ES5, tel que Node , Chrome, IE 9+, FF 4+, ou Safari 5+:

Object.keys(obj).length
2045
répondu Avi Flax 2014-04-23 16:59:37
la source

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

ensuite, vous pouvez utiliser ce dans les navigateurs plus anciens ainsi:

var len = Object.keys(obj).length;
142
répondu Renaat De Muynck 2018-03-22 13:31:52
la source

si vous utilisez Underscore.js vous pouvez utiliser _.size (merci @ douwe):

_.size(obj)

vous pouvez aussi utiliser _.touches 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. Dans la mesure du possible, ils concordent avec ECMA5 et s'en remettent à la natif de mise en œuvre.

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

128
répondu studgeek 2017-06-27 01:17:10
la source

the standard Object implementation ( ES5.1 Objet propriétés internes et méthodes ) ne nécessite pas un Object pour suivre 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'un Object sans itérer explicitement ou implicitement sur ses clés.

voici donc les alternatives les plus couramment utilisées:

1. L'objet d'ECMAScript.les touches()

Object.keys(obj).length; Œuvres interne itération sur les touches pour calculer un tableau temporaire et retourne sa longueur.

  • Pros Lisible et une syntaxe propre. Aucune bibliothèque ou code personnalisé requis sauf un shim si le support natif n'est pas disponible
  • Cons - mémoire aérienne due à la création du tableau.

2. Bibliothèque de solutions à base d'

de nombreux exemples tirés de bibliothèques ailleurs dans ce sujet sont des idiomes utiles dans le contexte de leur bibliothèque. Du point de vue de la performance, cependant, il n'y a rien à gagner par rapport à un code parfait sans Bibliothèque puisque toutes ces méthodes de bibliothèque encapsulent en fait soit une boucle pour-ou ES5 Object.keys (natif ou shimmed).

3. L'optimisation d'une boucle for

Le plus lente d'une telle boucle est généralement l'appel .hasOwnProperty() , en raison de la fonction Appel overhead. Donc quand je veux juste le nombre d'entrées d'un objet JSON, je saute juste l'appel .hasOwnProperty() si je sais qu'aucun code n'a fait ni ne prolongera Object.prototype .

sinon, votre code pourrait être très légèrement optimisé en faisant k local ( var k ) et en utilisant le PREFIX-increment operator ( ++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 méthode hasOwnProperty :

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. De toute façon, on peut s'attendre à un gain de performance très limité.

66
répondu Luc125 2018-04-27 16:14:11
la source

si vous rencontrez en fait un problème de performance, je suggère d'envelopper les appels qui ajoutent/suppriment des propriétés à/de l'objet avec une fonction qui incrémente/décrémente également un nom approprié (size?) propriété.

vous n'avez besoin de calculer le nombre initial de propriétés qu'une seule fois et de passer à autre chose. S'il n'y a pas de problème de performance, ne vous en souciez pas. Juste envelopper ce bout de code dans une fonction getNumberOfProperties(object) et être fait avec elle.

23
répondu Confusion 2013-02-11 22:42:43
la source

Je ne suis pas au courant d'aucune façon 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) alors vous pouvez itérer sur 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 compte change et que vous ne pouvez pas le faire, vous pouvez toujours faire une fonction:

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

par ici quand vous faites référence à myobj. __count__ la fonction va s'allumer et recalculer.

15
répondu Luke Bennett 2008-09-24 13:36:59
la source

comme indiqué par Avi Flax 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 aussi pour inclure les propriétés non énumérables, vous pouvez à la place 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 l'a déclaré ici cela a le même support de navigateur comme Object.keys

Cependant, en dans la plupart des cas, vous ne voudrez peut-être pas inclure les nonenumérables dans ce type d'opérations, mais il est toujours bon de connaître la différence;)

15
répondu BenderTheOffender 2017-05-23 13:31:39
la source

pour itérer sur L'objet de réponse Avi Flax.les touches(obj).la longueur est correcte pour un objet qui n'a pas les fonctions liées à

exemple:

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

versus

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 faire 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 mise en œuvre lodash https://lodash.com/docs#size

_.size(obj)

12
répondu Belldandu 2016-01-02 14:44:15
la source

pour ceux qui ont un trait de soulignement.js inclus dans leur projet, vous pouvez faire:

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

ou fonctionnelle style:

_.size({a:'', b:''}) // => 2
8
répondu hakunin 2012-01-04 13:04:06
la source

de: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

objet.defineProperty(obj, prop, descripteur)

, Vous pouvez l'ajouter à tous vos objets:

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

ou un seul objet:

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

exemple:

var myObj = {};
myObj.name  = "John Doe";
myObj.email = "[email protected]";
myObj.length; //output: 2

ajouté de cette façon, il ne sera pas

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

sortie:

name:John Doe
email:[email protected]

Note: il ne fonctionne pas dans les navigateurs < IE9.

6
répondu lepe 2015-08-21 06:44:11
la source

comment j'ai résolu ce problème est de construire ma propre mise en œuvre d'une liste de base qui conserve un enregistrement de combien d'éléments sont stockés dans l'objet. Elle est très simple. Quelque chose comme ceci:

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];
   }
}
5
répondu Click Upvote 2014-11-18 21:09:38
la source

pour ceux qui ont Ext JS 4 dans leur projet vous pouvez faire:

Ext.Object.getSize(myobj);

l'avantage de ceci est qu'il fonctionnera sur tous les navigateurs compatibles Ext (IE6-IE8 inclus), cependant, je crois que le temps de fonctionnement n'est pas mieux que O(n) cependant, comme avec d'autres solutions proposées.

3
répondu Mark Rhodes 2012-08-18 20:23:26
la source

comme répondu plus haut: Object.keys(obj).length

Mais: comme nous l'avons aujourd'hui une véritable Carte de la classe dans l'ES6, je le ferais suggèrent pour l'utiliser au lieu d'utiliser les propriétés d'un objet.

const map = new Map();
map.set("key", "value");
map.size; // THE fastest way
2
répondu Flavien Volken 2018-01-19 16:26:32
la source

Je ne pense pas que ce soit possible (du moins pas sans utiliser certains internes). Et je ne pense pas que vous gagneriez beaucoup en optimisant ceci.

1
répondu amix 2008-09-24 13:05:38
la source

si jQuery ci-dessus ne fonctionne pas, puis essayer

$(Object.Item).length
1
répondu codejoecode 2012-09-02 10:03:44
la source

j'essaie de le rendre disponible à tous les objets comme celui-ci:

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
0
répondu Taquatech 2018-04-14 15:51:03
la source

vous pouvez utiliser Object.keys(data).length pour trouver la longueur de l'objet JSON ayant des données clés

0
répondu Codemaker 2018-07-10 11:26:20
la source

Google Closure a une belle fonction pour cela... goog.objet.getCount (obj)

regardez goog.Documentation De L'Objet

-1
répondu Sebastian Perez 2011-12-13 18:04:04
la source

vous pouvez utiliser: Object.keys(objectName).length; & Object.values(objectName).length;

-1
répondu Fayaz 2018-02-28 10:09:18
la source

Autres questions sur javascript performance properties key count