keys - parcourir un tableau d'objet javascript




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

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 propriété magic __count__ , mais celle-ci a été supprimée quelque part autour de la version 4.)


Comme indiqué par Avi Flax https://.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 à la place 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, il a le même 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;)


Comment j'ai résolu ce problème est de construire ma propre implémentation d'une liste de base qui conserve un enregistrement du nombre d'éléments sont 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];
   }
}


J'essaie de le rendre accessible à tous les objets comme ceci:

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

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


L'implémentation Object standard ( Propriétés et méthodes internes de l'objet ES5.1 ) ne nécessite pas un 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 de ses clés .

Voici donc les alternatives les plus couramment 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.

  • Avantages - syntaxe lisible et propre. Aucune bibliothèque ou 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 la bibliothèque

Beaucoup d'exemples basés sur des bibliothèques ailleurs dans ce sujet 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é une boucle Object.keys ES5 ou en boucle (native ou shimmed).

3. Optimisation d'une boucle for

La partie la plus lente d'une telle boucle for est généralement l'appel .hasOwnProperty() , en raison de l'en-tête de l'appel de fonction. Donc, quand je veux juste le nombre d'entrées d'un objet JSON, je saute l'appel .hasOwnProperty() si je sais qu'aucun code n'a étendu et ne va étendre 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 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. Un gain de performance très limité peut être attendu de toute façon.


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 d'Ext (IE6-IE8 inclus), cependant, je crois que le temps d'exécution n'est pas meilleur que O (n) cependant, comme avec d'autres solutions suggérées.


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

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

ou style fonctionnel:

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

Si jQuery ci-dessus ne fonctionne pas, essayez

$(Object.Item).length

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 (taille?) Appropriée.

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. Enveloppez juste ce morceau de code dans une fonction getNumberOfProperties(object) et faites-en avec.


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;

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







key