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;

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

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

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

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;

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


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

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


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

20

Simplemente use esto para obtener length:

Object.keys(myObject).length

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

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;

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.


15

Utilizar:

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


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.


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

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

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


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

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

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


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.


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

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

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

// o/p 3

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.


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/


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


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.


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

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.


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

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.