Nombre d'éléments dans un objet javascript

104

Existe-t-il un moyen d'obtenir (de quelque part) le nombre d'éléments dans un objet javascript ?? (c.-à-d. complexité en temps constant).

Je ne trouve pas de propriété ou de méthode permettant de récupérer ces informations. Jusqu'à présent, je ne peux penser qu'à faire une itération dans toute la collection, mais c'est du temps linéaire.
C'est étrange qu'il n'y ait pas d'accès direct à la taille de l'objet, vous ne pensez pas.

EDIT:
je parle de l' Objectobjet (pas des objets en général):

var obj = new Object ;
GetFree
la source
5
Déjà répondu ici stackoverflow.com/questions/126100/… Object.keys (obj) .length
spats

Réponses:

155

Bien que les implémentations JS puissent suivre une telle valeur en interne, il n'y a pas de moyen standard de l'obtenir.

Dans le passé, la variante Javascript de Mozilla exposait le non-standard__count__ , mais elle a été supprimée avec la version 1.8.5.

Pour les scripts inter-navigateurs, vous êtes obligé d'itérer explicitement les propriétés et de vérifier hasOwnProperty():

function countProperties(obj) {
    var count = 0;

    for(var prop in obj) {
        if(obj.hasOwnProperty(prop))
            ++count;
    }

    return count;
}

Dans le cas d'implémentations compatibles ECMAScript 5, cela peut également être écrit comme (Félicitations à Avi Flax )

function countProperties(obj) {
    return Object.keys(obj).length;
}

Gardez à l'esprit que vous manquerez également des propriétés qui ne sont pas énumérables (par exemple, un tableau length).

Si vous utilisez un framework tel que jQuery, Prototype, Mootools, $ peu importe le dernier battage publicitaire, vérifiez s'ils sont fournis avec leur propre API de collections, ce qui pourrait être une meilleure solution à votre problème que d'utiliser des objets JS natifs.

Christoph
la source
11
Putain, j'oublie toujours hasOwnProperty. Trop de temps dans le pays .NET, je vous le dis. +1
annakata
2
jQuery utilise un objet pour ses collections qu'il obtient à partir de requêtes et expose cette valeur avec une propriété length.
Nosredna
6
Firefox4 __count__est parti :(
Timo Huovinen
1
Y a-t-il un moyen de faire cela sans un for in? Je suis dans le même type de liaison mais j'aimerais lui faire passer JSLint si possible.
lampadaire
1
pourquoi avons-nous besoin hasOwnProperty()?
swisswiss
100

Pour ce faire dans n'importe quel environnement compatible ES5

Object.keys(obj).length

(Prise en charge du navigateur à partir d' ici )
(Doc sur Object.keys ici , inclut la méthode que vous pouvez ajouter aux navigateurs non ECMA5)

ZelkiN
la source
2
Ce n'est pas la bonne question sur laquelle poser cette réponse. Avec cela, vous prenez toutes les clés de l'objet, en les plaçant dans un tableau nouvellement créé, puis en récupérant la propriété length de ce nouveau tableau.
GetFree
13
Ce n'est peut-être pas le programme le plus efficace, mais c'est le plus efficace pour les développeurs.
superluminaire
9

si vous utilisez déjà jQuery dans votre build, procédez comme suit:

$(yourObject).length

Cela fonctionne très bien pour moi sur les objets, et j'avais déjà jQuery comme dépendance.

IndélébileHeff
la source
5
Etrange ... ça ne marche pas pour moi. Je reçois toujours 1. La réponse de ZelkiN fonctionne pour moi.
mike rodent
3
Ce code renvoie toujours 1. Juste 1 objet. Il ne compte pas les éléments
BeRocket
5
function count(){
    var c= 0;
    for(var p in this) if(this.hasOwnProperty(p))++c;
    return c;
}

var O={a: 1, b: 2, c: 3};

count.call(O);
Kennebec
la source
2

AFAIK, il n'y a aucun moyen de le faire de manière fiable, sauf si vous passez à un tableau. Ce qui, honnêtement, ne semble pas étrange - il me semble assez simple que les tableaux soient dénombrables et que les objets ne le soient pas.

Probablement le plus proche que vous obtiendrez est quelque chose comme ça

// Monkey patching on purpose to make a point
Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this ) i++;
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 3

Mais cela crée des problèmes, ou du moins des questions. Toutes les propriétés créées par l'utilisateur sont comptées, y compris la fonction _length elle-même! Et bien que dans cet exemple simple, vous puissiez l'éviter en utilisant simplement une fonction normale, cela ne signifie pas que vous pouvez empêcher d'autres scripts de le faire. donc que fais-tu? Ignorer les propriétés de la fonction?

Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this )
  {
      if ( 'function' == typeof this[p] ) continue;
      i++;
  }
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 2

En fin de compte, je pense que vous devriez probablement abandonner l'idée de rendre vos objets dénombrables et trouver une autre façon de faire tout ce que vous faites.

Peter Bailey
la source
8
DANGER WILL ROBINSON! Ne pas proto contre l' objet! Tout descend d'Object, vous paralyserez le traitement du client comme celui-ci si vous effectuez un travail JS considérable.
annakata
5
Euh ... n'avez-vous pas lu la partie où j'ai écrit dans un commentaire "Monkey patching exprès pour faire un point" - allez, je l'ai fait délibérément pour que les gens ne reviennent pas un peu à ce sujet. De plus, même si je ne préconise pas le patching de singe, vous vous méprenez sur le fonctionnement de la chaîne de prototypes en Javascript si vous pensez que cela causerait des problèmes de performances video.yahoo.com/watch/111585/1027823
Peter Bailey
Alors ... c'est à faire ou à ne pas faire?
OscarRyz
Dans "Javascript: The Good Parts", il prototypera l'objet avec une méthode "create ()". Je crois que c'est le livre définitif sur Javascript.
Chris Dutrow
1

Le concept de nombre / longueur / dimensionnalité n'a pas vraiment de sens pour un objet, et en avoir besoin suggère que vous voulez vraiment un tableau pour moi.

Edit: m'a fait remarquer que vous voulez un O (1) pour cela. Pour autant que je sache, aucun moyen n'existe, j'en ai peur.

Annakata
la source
Il a proposé de se répéter, ce qu'est cette solution. Il avait besoin d'un moyen O (1) pour y parvenir ...
Thomas Hansen
Tu as plutot raison. Devrait vraiment lire les questions de manière plus approfondie.
annakata
En fait, les objets sont ce qui se rapproche le plus d'une carte dans JS. Les cartes ont de la longueur.
Cristian Vrabie le