Longitud de un objeto JavaScript

2384

Tengo un objeto JavaScript, ¿hay una forma de práctica recomendada incorporada o aceptada para obtener la longitud de este objeto?

const myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
Gareth Simpson
fuente
15
Los literales de objeto en javascript son por defecto matrices asociativas, por ejemplo, object.propertyName.propertyValue es lo mismo que object [propertyName] [propertyValue]
neitony
66
Se agregó una línea en Underscore.js que hace esto: stackoverflow.com/a/11346637/11236
ripper234
31
Una vez que la respuesta de línea es use Object.keys (myArray) .length como dijo @aeosynth.
Ranadheer Reddy
67
ok, ¿qué talObject.keys(obj).length
Muhammad Umer
55
¿Por qué no es válida la longitud de objeto? Devuelve el resultado correcto para mí.
Adrian M

Respuestas:

2624

La respuesta más sólida (es decir, que captura la intención de lo que está tratando de hacer mientras causa la menor cantidad de errores) sería:

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

Hay una especie de convención en JavaScript en la que no agrega cosas a Object.prototype , porque puede romper las enumeraciones en varias bibliotecas. Sin embargo, agregar métodos a Object generalmente es seguro.


Aquí hay una actualización a partir de 2016 y una implementación generalizada de ES5 y más allá. Para IE9 + y todos los otros navegadores modernos con capacidad ES5 +, puede usar Object.keys()para que el código anterior se convierta en:

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

Esto no tiene que modificar ningún prototipo existente ya Object.keys()que ahora está integrado.

Editar : los objetos pueden tener propiedades simbólicas que no se pueden devolver a través del método Object.key. Entonces la respuesta sería incompleta sin mencionarlos.

El tipo de símbolo se agregó al idioma para crear identificadores únicos para las propiedades del objeto. El principal beneficio del tipo de símbolo es la prevención de sobrescrituras.

Object.keyso Object.getOwnPropertyNamesno funciona para propiedades simbólicas. Para devolverlos necesitas usar 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

fuente
65
@Tres: su código puede romperse si alguien viene y anula la propiedad 'tamaño' sin saber que ya lo declaró en algún lugar del código, por lo que siempre vale la pena verificar si ya está definido
Vsync
19
@vsync Tienes mucha razón. Uno siempre debe implementar los controles de cordura necesarios :)
Tres
132
¿Por qué todos haciendo caso omiso de esto:Object.keys(obj).length
Muhammad Umer
33
@MuhammadUmer Probablemente porque ese método ni siquiera existía cuando se escribió esta respuesta. Incluso hoy, usarlo probablemente requerirá un polyfill para navegadores antiguos.
Chris Hayes
21
@stonyau IE8, IE9, IE10 son navegadores muertos que no reciben soporte de Microsoft. El usuario de IE8, IE9, IE10 recibe una notificación de Microsoft, de que usa un navegador antiguo y no compatible y debe esperar que las cosas no funcionen para ellos. support.microsoft.com/en-us/kb/3123303
Lukas Liesis
1709

Si sabe que no tiene que preocuparse por los hasOwnPropertycheques, puede hacerlo de manera muy simple:

Object.keys(myArray).length
aeosynth
fuente
23
¿Por qué no? por lo que sé, es un estándar: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
vsync
104
No es un método implementado universalmente , pero puede verificar qué navegador lo admite con esta tabla .
aeosynth
51
No es compatible con IE8 = no ir.
ripper234
22
hora de cambiar a firefox = desafortunadamente, cambiar no significa que los usuarios de su sitio web lo harán ...
mdup
82
@ ripper234 sin soporte de IE = tiempo para polyfill
John Dvorak
287

Actualizado : si está utilizando Underscore.js (¡recomendado, es liviano!), Entonces simplemente puede hacer

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

Si no es así , y no desea perder el tiempo con las propiedades de Object por cualquier razón, y ya está utilizando jQuery, un complemento es igualmente accesible:

$.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
fuente
77
_.size()fue la solución perfecta para mi proyecto Meteor , que tiene soporte para subrayar.js.
tokiovariable el
44
Uso guión bajo y esta publicación me recordó que no lo estoy usando lo suficiente en este proyecto. Si maneja objetos, debería tener underscore.js disponible.
jbolanos
3
Subrayado> (todos - ['lo-dash'])
Rayjax
underscorejs, cosas que deberían estar debajo de js :)
minhajul
1
@Babydead para distinguir las propiedades reales del objeto y las heredadas. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
ripper234
56

Aquí está la solución más cruzada del navegador.

Esto es mejor que la respuesta aceptada porque usa Object.keys nativo si existe. Por lo tanto, es el más rápido para todos los navegadores modernos.

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
fuente
66
Object.keys()devuelve una matriz que contiene los nombres de solo aquellas propiedades que son enumerables. Si desea una matriz con TODAS las propiedades, debe usarla Object.getOwnPropertyNames()en su lugar. Ver developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
John Slegers
35

No soy un experto en JavaScript, pero parece que tendría que recorrer los elementos y contarlos ya que Object no tiene un método de longitud:

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

@palmsey: Para ser justos con el OP, la documentación de JavaScript se refiere explícitamente al uso de variables de tipo Object de esta manera como "matrices asociativas".

jj33
fuente
8
No funcionará, porque también contará los métodos que se agregan a través del prototipo.
Lajos Meszaros
30

Este método obtiene todos los nombres de propiedad de su objeto en una matriz, por lo que puede obtener la longitud de esa matriz que es igual a la longitud de las claves de su objeto.

Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2
venkat7668
fuente
El método de claves @PatrickRoberts no devuelve propiedades de la cadena de prototipo. Entonces, ¿por qué la necesidad de hasOwnProperty aquí? También getOwnProperty volverá propiedades ocultas, como la longitud está en array etc.
Muhammad Umer
24

Para no meterse con el prototipo u otro código, puede construir y extender su propio objeto:

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 siempre usa el método add, la propiedad de longitud será correcta. Si le preocupa que usted u otros se olviden de usarlo, también puede agregar el contador de propiedades que los demás han publicado al método de longitud.

Por supuesto, siempre puedes sobrescribir los métodos. Pero incluso si lo hace, su código probablemente fallará notablemente, lo que facilitará la depuración. ;)

DanMan
fuente
Creo que esta es la mejor solución, ya que no requiere bucle con 'for', lo que podría ser costoso si la matriz es grande
Emeka Mbah
20

Aquí le mostramos cómo y no olvide verificar que la propiedad no esté en la cadena de prototipos:

var element_count = 0;
for(var e in myArray)
    if(myArray.hasOwnProperty(e))
        element_count++;
Doekman
fuente
20

Simplemente use esto para obtener length:

Object.keys(myObject).length
saurabhgoyal795
fuente
77
explique cómo su respuesta difiere de stackoverflow.com/a/6700/8632727
Patata
3
Tampoco deberías nombrar realmente tu objetomyArray
Barry Michael Doyle
2
@BarryMichaelDoyle, he cambiado eso :)
saurabhgoyal795
Bien, siempre es mejor nombrar sus variables de acuerdo con lo que realmente son. Hace que su código sea más legible para otros desarrolladores.
Barry Michael Doyle
44
Antes de la edición "myArray" -> "myObject", era idéntica a la segunda respuesta más votada.
Yunnosch
16

Aquí hay una solución completamente diferente que solo funcionará en navegadores más modernos (IE9 +, Chrome, Firefox 4+, Opera 11.60+, Safari 5.1+)

Ver jsFiddle

Configure su clase de matriz asociativa

/**
 * @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;
    }
});

Ahora puede usar este código de la siguiente manera ...

var a1 = new AssociativeArray();
a1["prop1"] = "test";
a1["prop2"] = 1234;
a1["prop3"] = "something else";
alert("Length of array is " + a1.length);
Aliado
fuente
Creo que eso no es seguro. Por ejemplo, no puede tener un elemento con una clave de "longitud", la instrucción a1 ["longitud"] = "Hola mundo"; no puede almacenar la entrada. También la instrucción a1 ["hasOwnProperty"] = "some prop"; rompe totalmente la función
Panos Theof
3
@PanosTheof No creo que quiera que almacene el valor si usa la lengthpropiedad, cualquier código que lo use tendría que asegurarse de que no intente almacenarlo length, pero supongo que sería lo mismo si fuera una matriz estándar también. Anular hasOwnPropertycualquier objeto probablemente produciría un resultado no deseado.
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>

Esto funciona para mi:

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

En algunos casos, es mejor simplemente almacenar el tamaño en una variable separada. Especialmente, si está agregando a la matriz por un elemento en un lugar y puede aumentar fácilmente el tamaño. Obviamente, funcionaría mucho más rápido si necesita verificar el tamaño con frecuencia.

Jānis Elmeris
fuente
15

Utilizar:

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

Mahendra Kulkarni
fuente
14

@palmsey: Para ser justos con el OP, los documentos de JavaScript en realidad se refieren explícitamente al uso de variables de tipo Object de esta manera como "matrices asociativas".

Y para ser justos con @palmsey, él era bastante correcto, no son matrices asociativas, definitivamente son objetos :), haciendo el trabajo de una matriz asociativa. Pero en lo que respecta al punto más amplio, definitivamente parece tener el derecho de acuerdo con este artículo bastante bueno que encontré:

JavaScript "Matrices asociativas" considerado perjudicial

Pero de acuerdo con todo esto, ¿no es la respuesta aceptada en sí misma una mala práctica?

Especifique una función prototype size () para Object

Si se ha agregado algo más al Object .prototype, el código sugerido fallará:

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

No creo que esa respuesta sea la aceptada, ya que no se puede confiar en que funcione si tiene algún otro código ejecutándose en el mismo contexto de ejecución. Para hacerlo de una manera robusta seguramente necesitará definir el método de tamaño dentro de myArray y verificar el tipo de miembros a medida que los recorre.

Polsonby
fuente
13

Si necesita una estructura de datos asociativa que exponga su tamaño, mejor use un mapa en lugar de un objeto.

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

¿Qué tal algo como esto?

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--; }}
}
alemán
fuente
11

Si tenemos el hash

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

podemos obtener la longitud usando la longitud de las teclas, que es la longitud del hash:

claves (hash) .length

abo-elleef
fuente
2
Esta es una gran respuesta, sin embargo, no puedo encontrar ninguna documentación para esta función de teclas. Por lo tanto, no puedo confiar en la compatibilidad con varios navegadores.
chim
1
¡Desafortunadamente, esta no es una respuesta tan buena como pensé por primera vez! Resulta que la función de teclas solo está disponible en las consolas web Chrome y Firefox. Si pone este código en un script, fallará con Uncaught ReferenceError: las claves no están definidas
chim
1
¿Cómo es esto diferente de la respuesta de 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
fuente
¿Cuál es más rápido entre los anteriores 3.
siluveru kiran kumar
Object.values ​​(myObject) .length
tdjprog
¿Cómo podemos decir que Object.values ​​(myObject) .length es más rápido? ¿Hay algún ejemplo? Gracias, @tdjprog
siluveru kiran kumar
intente esto en la consola:var myObject = {}; for (let i=0; i<10000000; i++) myObject[i] = i;
tdjprog
por qué Object.values ​​(myObject) .length más rápido, mientras que Object.entries (myObject) .length no da salida incluso después de algún tiempo, ¿cuál es la razón aquí? Gracias @tdjprog
siluveru kiran kumar
10

Si está utilizando AngularJS 1.x, puede hacer las cosas a la manera de AngularJS creando un filtro y utilizando el código de cualquiera de los otros ejemplos, como los siguientes:

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

Uso

En tu controlador:

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

O en tu opinión:

<any ng-expression="object | lengthOfObject"></any>
pcnate
fuente
44
El OP no ha pedido una versión de AngularJS. Esta no es una respuesta válida a la pregunta.
Francisco Hodge
10

La forma más simple es así

Object.keys(myobject).length

donde myobject es el objeto de lo que quieres la longitud

Mithu A Quayium
fuente
2
Esto parece ser solo una repetición de esta respuesta existente .
Pang
@Pang estuvo de acuerdo, y no proporciona ningún contexto adicional como lo hacen otras respuestas.
Místico
8

Si no le importa admitir Internet Explorer 8 o inferior, puede obtener fácilmente el número de propiedades en un objeto aplicando los siguientes dos pasos:

  1. Ejecútelo Object.keys()para obtener una matriz que contenga los nombres de solo aquellas propiedades que son enumerables o Object.getOwnPropertyNames()si desea incluir también los nombres de propiedades que no son enumerables.
  2. Obtenga la .lengthpropiedad de esa matriz.

Si necesita hacer esto más de una vez, podría ajustar esta lógica en una función:

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

Cómo usar esta función particular:

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

Vea también este violín para una demostración.

John Slegers
fuente
8

Use Object.keys(myObject).lengthpara obtener la longitud del objeto / matriz

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

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

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

// o/p 3
Dev216
fuente
7

Una variación de algunos de los anteriores es:

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

Es una forma un poco más elegante de integrar hasOwnProp.

Wade Harrell
fuente
6

Aquí hay una versión diferente de la respuesta de James Cogan. En lugar de pasar un argumento, prototipo de la clase Object y hacer el código más limpio.

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;

Ejemplo de jsfiddle: http://jsfiddle.net/qar4j/1/

Sherzod
fuente
66
Object.prototype- mala idea.
Dziad Borowy
@tborychowski, ¿puedes explicar por qué?
Mohamad
Aquí hay un artículo: bit.ly/1droWrG . No estoy diciendo que no se debe hacer, solo que necesitas saber todas las repercusiones antes de hacer esto.
Dziad Borowy
Si va a extender prototipos incorporados o rellenar una propiedad (es decir, parche de mono), hágalo correctamente: para la compatibilidad hacia adelante, verifique si la propiedad existe primero, luego haga que la propiedad no sea enumerable para que las propias claves de los objetos construidos no están contaminados. Para los métodos, use métodos reales . Mi recomendación: siga estos ejemplos que demuestran cómo agregar un método que se comporte de la manera más parecida posible a los métodos integrados.
user4642212
5

Simplemente puede usar Object.keys(obj).lengthen cualquier objeto para obtener su longitud. Object.keys devuelve una matriz que contiene todas las claves de objeto (propiedades) que pueden ser útiles para encontrar la longitud de ese objeto usando la longitud de la matriz correspondiente. Incluso puedes escribir una función para esto. Vamos a ser creativos y escribir un método para ello también (junto con una propiedad getter más conveniente):

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()

Místico
fuente
3
¿Cómo es esto diferente de la respuesta de aeosynth ?
Peter Mortensen
Es porque muestra cómo hacerlo como una función y un método de objeto global (más orientado a objetos y utiliza alguna forma de encapsulación); Sin embargo, la respuesta de aeosynth no.
Místico
Si va a extender prototipos incorporados o rellenar una propiedad (es decir, parche de mono), hágalo correctamente: para la compatibilidad hacia adelante, verifique si la propiedad existe primero, luego haga que la propiedad no sea enumerable para que las propias claves de los objetos construidos no están contaminados. Para los métodos, use métodos reales . Mi recomendación: siga estos ejemplos que demuestran cómo agregar un método que se comporte de la manera más parecida posible a los métodos integrados.
user4642212
Además, ¿cómo es la escritura de un método "más eficiente"?
user4642212
5

Siempre puede hacer Object.getOwnPropertyNames(myObject).lengthpara obtener el mismo resultado [].lengthque daría para una matriz normal.

Pian0_M4n
fuente
1
Object.keys()devuelve una matriz que contiene los nombres de solo aquellas propiedades que son enumerables. Si desea una matriz con TODAS las propiedades, debe usarla Object.getOwnPropertyNames()en su lugar. Ver developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
John Slegers
3
¿Cómo es esto diferente de la respuesta de aeosynth ?
Peter Mortensen
4

Podemos encontrar la longitud del objeto usando:

Object.values(myObject).length
solanki ...
fuente
4

Un poco tarde para el juego, pero una buena manera de lograr esto (solo IE9 +) es definir un captador mágico en la propiedad de longitud:

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

Y puedes usarlo así:

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

Daría 1.

MacroMan
fuente
1
Dejando a un lado los argumentos contra la modificación del prototipo, personalmente NUNCA tuve un error causado por él y para mí es uno de los puntos fuertes de JavaScript.
MacroMan
3

A continuación se muestra una versión de la respuesta de James Coglan en CoffeeScript para aquellos que han abandonado JavaScript directo :)

Object.size = (obj) ->
  size = 0
  size++ for own key of obj
  size
Eric Anderson
fuente
1
Probablemente quisiste decir size++ for own key of obj( own keyser sintaxis de azúcar en CoffeeScript). Usarlo hasOwnPropertydirectamente desde el objeto es peligroso, ya que se rompe cuando el objeto realmente tiene dicha propiedad.
Konrad Borowski el
2
El OP no solicitó una versión de CoffeeScript, ni está etiquetada como tal. Esta no es una respuesta válida a la pregunta.
Francisco Hodge