Longueur d'un objet JavaScript

2384

J'ai un objet JavaScript, existe-t-il un moyen intégré ou accepté de meilleures pratiques pour obtenir la longueur de cet objet?

const myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
Gareth Simpson
la source
15
Les littéraux d'objets en javascript sont par défaut des tableaux associatifs, par exemple object.propertyName.propertyValue est identique à object [propertyName] [propertyValue]
neitony
6
Ajout d'un one-liner dans Underscore.js qui fait cela: stackoverflow.com/a/11346637/11236
ripper234
31
Une fois la réponse en ligne utilisée, utilisez Object.keys (myArray) .length comme l'a dit @aeosynth.
Ranadheer Reddy
67
ok, que diriez-vousObject.keys(obj).length
Muhammad Umer
5
Pourquoi object.length n'est-il pas valide? Il renvoie le résultat correct pour moi.
Adrian M

Réponses:

2624

La réponse la plus robuste (c'est-à-dire qui capture l'intention de ce que vous essayez de faire tout en causant le moins de bogues) serait:

Object.size = function(obj) {
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};

// Get the size of an object
var size = Object.size(myObj);

Il y a une sorte de convention en JavaScript selon laquelle vous n'ajoutez rien à Object.prototype , car cela peut casser les énumérations dans diverses bibliothèques. Cependant, ajouter des méthodes à Object est généralement sûr.


Voici une mise à jour à partir de 2016 et un déploiement généralisé d'ES5 et au-delà. Pour IE9 + et tous les autres navigateurs modernes ES5 +, vous pouvez utiliser Object.keys()le code ci-dessus comme suit:

var size = Object.keys(myObj).length;

Cela ne doit modifier aucun prototype existant car il Object.keys()est maintenant intégré.

Edit : les objets peuvent avoir des propriétés symboliques qui ne peuvent pas être retournées via la méthode Object.key. La réponse serait donc incomplète sans les mentionner.

Le type de symbole a été ajouté au langage pour créer des identificateurs uniques pour les propriétés des objets. Le principal avantage du type Symbol est la prévention des écrasements.

Object.keysou Object.getOwnPropertyNamesne fonctionne pas pour les propriétés symboliques. Pour les retourner, vous devez utiliser Object.getOwnPropertySymbols.

var person = {
  [Symbol('name')]: 'John Doe',
  [Symbol('age')]: 33,
  "occupation": "Programmer"
};

const propOwn = Object.getOwnPropertyNames(person);
console.log(propOwn.length); // 1

let propSymb = Object.getOwnPropertySymbols(person);
console.log(propSymb.length); // 2

la source
65
@Tres - votre code peut être cassé si quelqu'un vient outrepasser la propriété 'size' sans savoir que vous l'avez déjà déclarée quelque part dans le code, il vaut donc toujours la peine de vérifier si elle est déjà définie
vsync
19
@vsync Vous avez très raison. Il faut toujours mettre en œuvre les vérifications de santé mentale nécessaires :)
Tres
132
Pourquoi tout le monde ignore-t-il cela: Object.keys(obj).length
Muhammad Umer
33
@MuhammadUmer Probablement parce que cette méthode n'existait même pas lorsque cette réponse a été écrite. Même aujourd'hui, son utilisation nécessitera probablement un polyfill pour les anciens navigateurs.
Chris Hayes
21
@stonyau IE8, IE9, IE10 sont des navigateurs morts qui ne sont pas pris en charge par Microsoft. Les utilisateurs d'IE8, IE9 et IE10 reçoivent une notification de Microsoft leur indiquant qu'ils utilisent un ancien navigateur non pris en charge et doivent s'attendre à ce que ces éléments ne fonctionnent pas pour eux. support.microsoft.com/en-us/kb/3123303
Lukas Liesis
1709

Si vous savez que vous n'avez pas à vous soucier des hasOwnPropertycontrôles, vous pouvez le faire très simplement:

Object.keys(myArray).length
aeosynth
la source
23
pourquoi pas? d'après ce que je sais, c'est une norme: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
vsync
104
Ce n'est pas une méthode universellement implémentée , mais vous pouvez vérifier quel navigateur la prend en charge avec ce tableau .
aeosynth
51
Pas de support IE8 = non.
ripper234
22
il est temps de passer à firefox = malheureusement, votre changement ne signifie pas que les utilisateurs de votre site Web le feront ...
mdup
82
@ ripper234 pas de support IE = temps de polyfill
John Dvorak
287

Mise à jour : si vous utilisez Underscore.js (recommandé, c'est léger!), Alors vous pouvez simplement faire

_.size({one : 1, two : 2, three : 3});
=> 3

Sinon , et vous ne voulez pas jouer avec les propriétés d'objet pour une raison quelconque, et utilisez déjà jQuery, un plugin est également accessible:

$.assocArraySize = function(obj) {
    // http://stackoverflow.com/a/6700/11236
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};
ripper234
la source
7
_.size()était la solution parfaite pour mon projet Meteor , qui prend en charge underscore.js.
tokyovariable
4
J'utilise le soulignement et ce message m'a juste rappelé que je ne l'utilisais pas assez dans ce projet. Si vous gérez des objets, vous devriez avoir underscore.js disponible.
jbolanos
3
Underscore> (all - ['lo-dash'])
Rayjax
underscorejs, les choses qui devraient être sous js :)
minhajul
1
@Babydead pour distinguer les propriétés réelles de l'objet de celles héritées. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
ripper234
56

Voici la solution la plus multi-navigateurs.

C'est mieux que la réponse acceptée car elle utilise des Object.keys natifs s'il existe. Ainsi, c'est le plus rapide pour tous les navigateurs modernes.

if (!Object.keys) {
    Object.keys = function (obj) {
        var arr = [],
            key;
        for (key in obj) {
            if (obj.hasOwnProperty(key)) {
                arr.push(key);
            }
        }
        return arr;
    };
}

Object.keys(obj).length;
Joon
la source
6
Object.keys()renvoie un tableau qui contient uniquement les noms des propriétés énumérables. Si vous voulez un tableau avec TOUTES les propriétés, vous devez utiliser à la Object.getOwnPropertyNames()place. Voir developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
John Slegers
35

Je ne suis pas un expert JavaScript, mais il semble que vous deviez parcourir les éléments et les compter car Object n'a pas de méthode de longueur:

var element_count = 0;
for (e in myArray) {  if (myArray.hasOwnProperty(e)) element_count++; }

@palmsey: Pour être honnête avec l'OP, la documentation JavaScript se réfère en fait explicitement à l'utilisation de variables de type Object de cette manière en tant que "tableaux associatifs".

jj33
la source
8
Ne fonctionnera pas, car il comptera également les méthodes qui sont ajoutées via le prototype.
Lajos Meszaros,
30

Cette méthode obtient tous les noms de propriétés de votre objet dans un tableau, vous pouvez donc obtenir la longueur de ce tableau qui est égale à la longueur des clés de votre objet.

Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2
venkat7668
la source
La méthode de clés @PatrickRoberts ne renvoie pas les propriétés de la chaîne de prototypes. Alors pourquoi le besoin de hasOwnProperty ici. GetOwnProperty retournera également les propriétés cachées, car la longueur est dans le tableau, etc.
Muhammad Umer
24

Pour ne pas jouer avec le prototype ou un autre code, vous pouvez créer et étendre votre propre objet:

function Hash(){
    var length=0;
    this.add = function(key, val){
         if(this[key] == undefined)
         {
           length++;
         }
         this[key]=val;
    }; 
    this.length = function(){
        return length;
    };
}

myArray = new Hash();
myArray.add("lastname", "Simpson");
myArray.add("age", 21);
alert(myArray.length()); // will alert 2

Si vous utilisez toujours la méthode add, la propriété length sera correcte. Si vous craignez que vous ou d'autres personnes l'utilisiez, vous pouvez également ajouter le compteur de propriétés que les autres ont publié dans la méthode de longueur.

Bien sûr, vous pouvez toujours remplacer les méthodes. Mais même si vous le faites, votre code échouera probablement sensiblement, ce qui facilitera le débogage. ;)

DanMan
la source
Je pense que c'est la meilleure solution car elle ne nécessite pas de boucle avec 'for', ce qui pourrait être coûteux si la baie est grande
Emeka Mbah
20

Voici comment et n'oubliez pas de vérifier que la propriété n'est pas sur la chaîne prototype:

var element_count = 0;
for(var e in myArray)
    if(myArray.hasOwnProperty(e))
        element_count++;
doekman
la source
20

Utilisez-le simplement pour obtenir length:

Object.keys(myObject).length
saurabhgoyal795
la source
7
veuillez expliquer en quoi votre réponse diffère de stackoverflow.com/a/6700/8632727
Patata
3
Vous ne devriez pas non plus vraiment nommer votre objetmyArray
Barry Michael Doyle
2
@BarryMichaelDoyle j'ai changé ça :)
saurabhgoyal795
Bon, il vaut toujours mieux nommer vos variables en fonction de ce qu'elles sont réellement. Rend votre code plus lisible pour les autres développeurs.
Barry Michael Doyle
4
Avant la modification de "myArray" -> "myObject", celle-ci était identique à la deuxième réponse la plus élevée.
Yunnosch
16

Voici une solution complètement différente qui ne fonctionnera que dans les navigateurs plus modernes (IE9 +, Chrome, Firefox 4+, Opera 11.60+, Safari 5.1+)

Voir jsFiddle

Configurez votre classe de tableau associatif

/**
 * @constructor
 */
AssociativeArray = function () {};

// Make the length property work
Object.defineProperty(AssociativeArray.prototype, "length", {
    get: function () {
        var count = 0;
        for (var key in this) {
            if (this.hasOwnProperty(key))
                count++;
        }
        return count;
    }
});

Vous pouvez maintenant utiliser ce code comme suit ...

var a1 = new AssociativeArray();
a1["prop1"] = "test";
a1["prop2"] = 1234;
a1["prop3"] = "something else";
alert("Length of array is " + a1.length);
Allié
la source
Je pense que ce n'est pas sûr. Par exemple, il ne peut pas avoir d'élément avec une clé de "longueur", l'instruction a1 ["longueur"] = "Bonjour tout le monde"; ne parvient pas à stocker l'entrée. Aussi la déclaration a1 ["hasOwnProperty"] = "certains accessoires"; totalement la fonction
Panos Theof
3
@PanosTheof Je ne pense pas que vous voudriez qu'il stocke la valeur si vous utilisez la lengthpropriété, tout code qui l'utilise devra s'assurer qu'il n'essaye pas de se stocker length, mais je suppose que ce serait la même chose si c'était le cas. un tableau standard aussi. Surcharger hasOwnPropertyn'importe quel objet produirait très probablement un résultat indésirable.
Ally
16

<script>
myObj = {"key1" : "Hello", "key2" : "Goodbye"};
var size = Object.keys(myObj).length;
console.log(size);
</script>

<p id="myObj">The number of <b>keys</b> in <b>myObj</b> are: <script>document.write(size)</script></p>

Cela fonctionne pour moi:

var size = Object.keys(myObj).length;
Giovanni G. PY
la source
15

Dans certains cas, il est préférable de simplement stocker la taille dans une variable distincte. Surtout, si vous ajoutez au tableau un élément en un seul endroit et pouvez facilement augmenter la taille. Cela fonctionnerait évidemment beaucoup plus rapidement si vous devez vérifier la taille souvent.

Jānis Elmeris
la source
15

Utilisation:

var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
obj = Object.keys(myArray).length;
console.log(obj)

Mahendra Kulkarni
la source
14

@palmsey: Pour être juste avec l'OP, les documents javascript se réfèrent en fait explicitement à l'utilisation de variables de type Object de cette manière en tant que "tableaux associatifs".

Et pour être honnête avec @palmsey, il avait tout à fait raison, ce ne sont pas des tableaux associatifs, ce sont certainement des objets :) - faire le travail d'un tableau associatif. Mais en ce qui concerne le point plus large, vous semblez définitivement en avoir le droit selon cet article plutôt fin que j'ai trouvé:

Les «tableaux associatifs» JavaScript considérés comme nuisibles

Mais d'après tout cela, la réponse acceptée n'est-elle pas en soi une mauvaise pratique?

Spécifiez une fonction prototype size () pour Object

Si autre chose a été ajouté au Object .prototype, le code suggéré échouera:

<script type="text/javascript">
Object.prototype.size = function () {
  var len = this.length ? --this.length : -1;
    for (var k in this)
      len++;
  return len;
}
Object.prototype.size2 = function () {
  var len = this.length ? --this.length : -1;
    for (var k in this)
      len++;
  return len;
}
var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
alert("age is " + myArray["age"]);
alert("length is " + myArray.size());
</script>

Je ne pense pas que cette réponse devrait être acceptée car elle ne peut pas être approuvée pour fonctionner si vous avez un autre code en cours d'exécution dans le même contexte d'exécution. Pour le faire de manière robuste, vous devez sûrement définir la méthode de taille dans myArray et vérifier le type des membres à mesure que vous les parcourez.

Polsonby
la source
13

Si vous avez besoin d'une structure de données associative qui expose sa taille, mieux utiliser une carte au lieu d'un objet.

const myMap = new Map();
myMap.set("firstname", "Gareth");
myMap.set("lastname", "Simpson");
myMap.set("age", 21);
myMap.size; // 3
Oriol
la source
11

Et quelque chose comme ça -

function keyValuePairs() {
    this.length = 0;
    function add(key, value) { this[key] = value; this.length++; }
    function remove(key) { if (this.hasOwnProperty(key)) { delete this[key]; this.length--; }}
}
Jerry
la source
11

Si nous avons le hachage

hash = {"a": "b", "c": "d"};

nous pouvons obtenir la longueur en utilisant la longueur des clés qui est la longueur du hachage:

clés (hachage) .longueur

abo-elleef
la source
2
C'est une excellente réponse, mais je ne trouve aucune documentation pour cette fonction de touches. Je ne peux donc pas avoir confiance en la prise en charge de plusieurs navigateurs.
chim
1
Malheureusement, ce n'est pas une aussi bonne réponse que je ne le pensais! Il s'avère que la fonction de touches n'est disponible que dans les consoles Web Chrome et Firefox. Si vous mettez ce code dans un script, il échouera avec Uncaught ReferenceError: les clés ne sont pas définies
chim
1
En quoi est-ce différent de la réponse d' Aeosynth ?
Peter Mortensen
11
var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
  1. Object.values ​​(myObject) .length
  2. Object.entries (myObject) .length
  3. Object.keys (myObject) .length
tdjprog
la source
Lequel est le plus rapide parmi les 3 ci-dessus.
siluveru kiran kumar
Object.values ​​(myObject) .length
tdjprog
comment pouvons-nous dire qu'il Object.values ​​(myObject) .length est plus rapide est-il un exemple Merci, @tdjprog
siluveru kiran kumar
essayez simplement ceci dans la console:var myObject = {}; for (let i=0; i<10000000; i++) myObject[i] = i;
tdjprog
pourquoi Object.values ​​(myObject) .length plus rapide, alors que Object.entries (myObject) .length ne donne pas de sortie même après un certain temps, quelle est la raison ici? Merci @tdjprog
siluveru kiran kumar
10

Si vous utilisez AngularJS 1.x, vous pouvez faire les choses à la manière d'AngularJS en créant un filtre et en utilisant le code de l'un des autres exemples tels que les suivants:

// Count the elements in an object
app.filter('lengthOfObject', function() {
  return function( obj ) {
    var size = 0, key;
    for (key in obj) {
      if (obj.hasOwnProperty(key)) size++;
    }
   return size;
 }
})

Usage

Dans votre contrôleur:

$scope.filterResult = $filter('lengthOfObject')($scope.object)

Ou selon vous:

<any ng-expression="object | lengthOfObject"></any>
pcnate
la source
4
L'OP n'a pas demandé de version AngularJS. Ce n'est pas une réponse valable à la question.
Francisco Hodge
10

La façon la plus simple est comme ça

Object.keys(myobject).length

où mon objet est l'objet de ce que vous voulez la longueur

Mithu A Quayium
la source
2
Cela semble être juste une répétition de cette réponse existante .
Pang
@Pang a accepté, et il ne fournit pas de contexte supplémentaire comme le font les autres réponses.
Mystical
8

Si vous ne vous souciez pas de la prise en charge d'Internet Explorer 8 ou d'une version antérieure, vous pouvez facilement obtenir le nombre de propriétés d'un objet en appliquant les deux étapes suivantes:

  1. Exécutez soit Object.keys()pour obtenir un tableau contenant uniquement les noms des propriétés énumérables ouObject.getOwnPropertyNames() si vous souhaitez également inclure les noms des propriétés non énumérables.
  2. Obtenez la .lengthpropriété de ce tableau.

Si vous devez effectuer cette opération plusieurs fois, vous pouvez encapsuler cette logique dans une fonction:

function size(obj, enumerablesOnly) {
    return enumerablesOnly === false ?
        Object.getOwnPropertyNames(obj).length :
        Object.keys(obj).length;
}

Comment utiliser cette fonction particulière:

var myObj = Object.create({}, {
    getFoo: {},
    setFoo: {}
});
myObj.Foo = 12;

var myArr = [1,2,5,4,8,15];

console.log(size(myObj));        // Output : 1
console.log(size(myObj, true));  // Output : 1
console.log(size(myObj, false)); // Output : 3
console.log(size(myArr));        // Output : 6
console.log(size(myArr, true));  // Output : 6
console.log(size(myArr, false)); // Output : 7

Voir aussi ce violon pour une démo.

John Slegers
la source
8

Utilisez Object.keys(myObject).lengthpour obtenir la longueur de l'objet / du tableau

var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;

console.log(Object.keys(myObject).length); //3
shaheb
la source
8
const myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;

console.log(Object.keys(myObject).length)

// o/p 3
Dev216
la source
7

Une variation de certains des éléments ci-dessus est la suivante:

var objLength = function(obj){    
    var key,len=0;
    for(key in obj){
        len += Number( obj.hasOwnProperty(key) );
    }
    return len;
};

C'est une façon un peu plus élégante d'intégrer hasOwnProp.

wade harrell
la source
6

Voici une version différente de la réponse de James Cogan. Au lieu de passer un argument, il suffit de créer un prototype de la classe Object et de rendre le code plus propre.

Object.prototype.size = function () {
    var size = 0,
        key;
    for (key in this) {
        if (this.hasOwnProperty(key)) size++;
    }
    return size;
};

var x = {
    one: 1,
    two: 2,
    three: 3
};

x.size() === 3;

exemple jsfiddle: http://jsfiddle.net/qar4j/1/

Sherzod
la source
6
Object.prototype- mauvaise idée.
Dziad Borowy,
@tborychowski pouvez-vous expliquer pourquoi?
Mohamad
voici un article: bit.ly/1droWrG . Je ne dis pas que cela ne doit pas être fait, mais seulement que vous devez connaître toutes les répercussions avant de faire cela.
Dziad Borowy
Si vous allez étendre des prototypes intégrés ou remplir une propriété (c'est-à-dire monkey-patch), veuillez le faire correctement: pour la compatibilité ascendante, vérifiez si la propriété existe d'abord, puis rendez la propriété non énumérable afin que les propres clés des objets construits ne sont pas pollués. Pour les méthodes, utilisez des méthodes réelles . Ma recommandation: suivez ces exemples qui montrent comment ajouter une méthode qui se comporte aussi étroitement que possible comme les méthodes intégrées.
user4642212
5

Vous pouvez simplement l'utiliser Object.keys(obj).lengthsur n'importe quel objet pour obtenir sa longueur. Object.keys renvoie un tableau contenant toutes les clés d' objet (propriétés) qui peuvent être utiles pour trouver la longueur de cet objet en utilisant la longueur du tableau correspondant. Vous pouvez même écrire une fonction pour cela. Soyons créatifs et écrivons également une méthode pour cela (avec une propriété getter plus pratique):

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

console.log(objLength({a:1, b:"summit", c:"nonsense"}));

// Works perfectly fine
var obj = new Object();
obj['fish'] = 30;
obj['nullified content'] = null;
console.log(objLength(obj));

// It also works your way, which is creating it using the Object constructor
Object.prototype.getLength = function() {
   return Object.keys(this).length;
}
console.log(obj.getLength());

// You can also write it as a method, which is more efficient as done so above

Object.defineProperty(Object.prototype, "length", {get:function(){
    return Object.keys(this).length;
}});
console.log(obj.length);

// probably the most effictive approach is done so and demonstrated above which sets a getter property called "length" for objects which returns the equivalent value of getLength(this) or this.getLength()

Mystique
la source
3
En quoi est-ce différent de la réponse d' aeosynth ?
Peter Mortensen
C'est parce qu'il montre comment le faire en tant que fonction et méthode d'objet globale (plus orientée objet et utilise une certaine forme d'encapsulation); mais pas la réponse d'aeosynth .
Mystical
Si vous allez étendre des prototypes intégrés ou remplir une propriété (c'est-à-dire monkey-patch), veuillez le faire correctement: pour la compatibilité ascendante, vérifiez si la propriété existe d'abord, puis rendez la propriété non énumérable afin que les propres clés des objets construits ne sont pas pollués. Pour les méthodes, utilisez des méthodes réelles . Ma recommandation: suivez ces exemples qui montrent comment ajouter une méthode qui se comporte aussi étroitement que possible comme les méthodes intégrées.
user4642212
De plus, comment l'écriture d'une méthode est-elle «plus efficace»?
user4642212
5

Vous pouvez toujours faire Object.getOwnPropertyNames(myObject).lengthpour obtenir le même résultat que [].lengthpour un tableau normal.

Pian0_M4n
la source
1
Object.keys()renvoie un tableau qui contient uniquement les noms des propriétés énumérables. Si vous voulez un tableau avec TOUTES les propriétés, vous devez utiliser à la Object.getOwnPropertyNames()place. Voir developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
John Slegers
3
En quoi est-ce différent de la réponse d' aeosynth ?
Peter Mortensen
4

Nous pouvons trouver la longueur de l'objet en utilisant:

Object.values(myObject).length
solanki ...
la source
4

Un peu en retard dans le jeu, mais un bon moyen d'y parvenir (IE9 + uniquement) est de définir un getter magique sur la propriété length:

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

Et vous pouvez simplement l'utiliser comme ceci:

var myObj = { 'key': 'value' };
myObj.length;

Donnerait 1.

MacroMan
la source
1
Mis à part les arguments contre la modification du prototype, personnellement, je n'ai JAMAIS eu de bogue causé par cela et pour moi, c'est l'un des points forts de JavaScript.
MacroMan
3

Vous trouverez ci-dessous une version de la réponse de James Coglan en CoffeeScript pour ceux qui ont abandonné le JavaScript direct :)

Object.size = (obj) ->
  size = 0
  size++ for own key of obj
  size
Eric Anderson
la source
1
Vous vouliez probablement dire size++ for own key of obj( own keyétant le sucre de syntaxe dans CoffeeScript). L'utilisation hasOwnPropertydirecte à partir de l'objet est dangereuse, car elle se brise lorsque l'objet possède réellement une telle propriété.
Konrad Borowski
2
L'OP n'a pas demandé de version CoffeeScript, ni étiqueté comme tel. Ce n'est pas une réponse valable à la question.
Francisco Hodge