Question

Quel est le moyen le 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é supprimée quelque part autour de la version 4.)

Était-ce utile?

La solution

Effectuez cette opération dans tout environnement compatible ES5 , tel que Noeud , Chrome, IE 9+, Firefox 4+ ou Safari 5+:

Object.keys(obj).length

Autres conseils

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 également l'utiliser dans les anciens navigateurs:

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

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

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

Je recommande vivement Underscore, une bibliothèque compacte permettant de faire beaucoup de choses de base. Dans la mesure du possible, ils correspondent à ECMA5 et s’appliquent à l’implémentation native.

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

L'implémentation d'objet standard ( Propriétés internes de l'objet ES5.1 and Methods ) ne nécessite pas de Object suivi de son nombre de clés / propriétés; il ne doit donc exister aucun moyen standard de déterminer la taille d'un Object.keys(obj).length; sans itérer explicitement ou implicitement sur ses clés.

Voici donc les alternatives les plus couramment utilisées:

1. Object.keys () d'ECMAScript

Object.keys Fonctionne en en interne en parcourant les clés pour calculer un tableau temporaire et renvoie sa longueur.

  • Avantages : syntaxe lisible et claire. Aucune bibliothèque ni code personnalisé requis, sauf un shim si le support natif n'est pas disponible
  • Inconvénients : surcharge de mémoire due à la création du tableau.

2. Solutions basées sur des bibliothèques

De nombreux exemples basés sur les 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’ya 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 .hasOwnProperty() (natif ou shimmed).

3. Optimiser une boucle for

La partie la plus lente d'une telle boucle for est généralement l'appel Object.prototype en raison de la surcharge de l'appel de fonction. Ainsi, lorsque je veux juste le nombre d'entrées d'un objet JSON, je passe simplement l'appel k si je sais qu'aucun code n'a été ni ne sera étendu var k.

Sinon, votre code pourrait être très légèrement optimisé en rendant ++count local (hasOwnProperty) et en utilisant l'opérateur prefix-increment (<=>) 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:

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

Que cela soit plus rapide ou non sur un environnement donné est une question d'analyse comparative. De toute façon, on peut s’attendre à un gain de performance très limité.

Si vous rencontrez réellement un problème de performances, je vous 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é (size?) nommée de manière appropriée.

Il vous suffit de calculer le nombre initial de propriétés une fois, puis de continuer à partir de là. S'il n'y a pas de problème de performances, ne vous inquiétez pas. Il suffit d’envelopper ce morceau de code dans une fonction getNumberOfProperties(object) et d’en finir.

Je ne suis au courant d'aucun moyen de le faire. Cependant, pour limiter les itérations au minimum, vous pouvez vérifier l'existence de __count__ et si elle n'existe pas (c'est-à-dire pas Firefox), vous pouvez itérer sur l'objet et le définir pour une utilisation ultérieure, par exemple:

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

Ainsi, tout navigateur prenant en charge <=> l’utiliserait, et les itérations ne seraient effectuées que pour les autres. 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(); }
}

Ainsi, chaque fois que vous référencez myobj. <=> la fonction sera déclenchée et recalculée.

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 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 , le navigateur prend en charge le même support que Object.keys

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

Pour itérer sur Avi Flax, répondez Object.keys (obj) .length est correct pour un objet qui ne possède pas de fonctions liées à celui-ci

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 placez pas de fonctions dans un objet pour lequel vous souhaitez compter le nombre de clés

  2. utilisez un objet séparé ou créez un nouvel objet spécialement pour les fonctions (si vous souhaitez compter le nombre de fonctions présentes dans le fichier à l'aide de Object.keys(obj).length)

aussi oui j'ai utilisé le _ ou le module de soulignement de nodejs dans mon exemple

La

documentation est disponible ici http://underscorejs.org/ , ainsi que sa source sur github et divers autres info

Et enfin, une implémentation de lodash https://lodash.com/docs#size

_.size(obj)

Pour ceux qui ont Underscore.js inclus dans leur projet, vous pouvez faire:

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

ou style fonctionnel:

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

De: https: //developer.mozilla. org / fr / docs / Web / JavaScript / Référence / Global_Objects / Object / defineProperty

  

Object.defineProperty (obj, prop, descriptor)

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 = "leaked@example.com";
myObj.length; //output: 2

Ajouté de cette façon, il ne sera pas affiché dans les boucles for..in:

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

Sortie:

name:John Doe
email:leaked@example.com

Remarque: cela ne fonctionne pas dans < Navigateurs IE9.

comme répondu ci-dessus: Object.keys(obj).length

Mais: comme nous avons maintenant un véritable Map classe dans ES6, je suggère d'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

Pour résoudre ce problème, j'ai créé ma propre implémentation d'une liste de base qui enregistre le nombre d'éléments stockés dans l'objet. C'est très simple. Quelque chose comme ça:

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

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

Ext.Object.getSize(myobj);

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), contrairement à d'autres solutions suggérées.

Vous pouvez utiliser Object.keys(data).length pour rechercher la longueur d'un objet JSON contenant des données de clé

Si jQuery ci-dessus ne fonctionne pas, essayez

$(Object.Item).length

OP n'a pas spécifié si l'objet est une liste de noeuds. Si c'est le cas, vous pouvez simplement utiliser la méthode length dessus. Exemple:

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

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

J'essaie de le rendre disponible pour 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

Google Closure a une fonction intéressante pour cela ... goog.object.getCount (obj)

consultez la documentation de goog.Object

.

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top