Pregunta ¿Cómo contar eficientemente el número de claves / propiedades de un objeto en JavaScript?


¿Cuál es la forma más rápida de contar el número de claves / propiedades de un objeto? ¿Es posible hacer esto sin iterar sobre el objeto? es decir, sin hacer

var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) count++;

(Firefox proporcionó una magia __count__ propiedad, pero esto fue eliminado en algún lugar alrededor de la versión 4.)


1192
2017-09-24 08:56


origen


Respuestas:


Para hacer esto en cualquier entorno compatible con ES5, como Nodo, Chrome, IE 9+, FF 4+ o Safari 5+:

Object.keys(obj).length

1982
2018-02-03 17:47



Puedes usar este código:

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

Entonces también puedes usar esto en navegadores más antiguos:

var len = Object.keys(obj).length;

140
2018-04-15 10:48



Si estás usando Underscore.js puedes usar _.tamaño (gracias @douwe):
_.size(obj)

Alternativamente también puedes usar _.llaves lo que podría ser más claro para algunos:
_.keys(obj).length 

Recomiendo Underscore, es una biblioteca estrecha para hacer muchas cosas básicas. Siempre que sea posible, coinciden con ECMA5 y difieren a la implementación nativa.

De lo contrario, apoyo la respuesta de @ Avi. Lo edité para agregar un enlace al documento MDC que incluye el método keys () que puede agregar a los navegadores que no son ECMA5.


126
2018-05-16 15:24



La implementación estándar de Objetos (ES5.1 Object Internal Properties and Methods) no requiere un Object para rastrear su número de claves / propiedades, por lo que no debería haber una forma estándar de determinar el tamaño de una Object sin iterar explícita o implícitamente sobre sus claves.

Así que aquí están las alternativas más comúnmente utilizadas:

1. Object.keys de ECMAScript ()

Object.keys(obj).length; Trabajos por internamente iterando sobre las teclas para calcular una matriz temporal y devuelve su longitud.

  • Pros - Sintaxis legible y legible. No se requiere ninguna biblioteca o código personalizado, excepto un shim si el soporte nativo no está disponible
  • Contras - Sobrecarga de memoria debido a la creación de la matriz.

2. Soluciones basadas en la biblioteca

Muchos ejemplos basados ​​en bibliotecas en otros lugares de este tema son expresiones útiles en el contexto de su biblioteca. Desde el punto de vista del rendimiento, sin embargo, no hay nada que ganar en comparación con un código perfecto sin biblioteca, ya que todos esos métodos de biblioteca realmente encapsulan un bucle for o ES5. Object.keys (nativo o deslumbrado).

3. Optimizar un bucle for

los parte más lenta de tal bucle for es generalmente el .hasOwnProperty() llamada, debido a la llamada a la función de sobrecarga. Entonces, cuando solo quiero el número de entradas de un objeto JSON, me salteo el .hasOwnProperty() llamar si sé que ningún código ni se extenderá Object.prototype.

De lo contrario, su código podría optimizarse muy ligeramente haciendo k local (var k) y usando el operador de incremento de prefijo (++count) en lugar de postfix.

var count = 0;
for (var k in myobj) if (myobj.hasOwnProperty(k)) ++count;

Otra idea se basa en almacenar en caché el hasOwnProperty método:

var hasOwn = Object.prototype.hasOwnProperty;
var count = 0;
for (var k in myobj) if (hasOwn.call(myobj, k)) ++count;

Si esto es más rápido o no en un ambiente dado es una cuestión de evaluación comparativa. De todos modos, se puede esperar una ganancia de rendimiento muy limitada.


65
2017-09-24 09:11



Si en realidad se encuentra con un problema de rendimiento, le sugiero que ajuste las llamadas que agregan / quitan propiedades al / del objeto con una función que también incrementa / disminuye una propiedad apropiadamente llamada (tamaño?).

Solo necesita calcular el número inicial de propiedades una vez y continuar desde allí. Si no hay un problema de rendimiento real, no se moleste. Solo envuelve ese bit de código en una función getNumberOfProperties(object) y termine con esto.


23
2017-09-24 09:13



No conozco ninguna forma de hacerlo, sin embargo, para mantener las iteraciones al mínimo, podría intentar verificar la existencia de __count__ y si no existe (es decir, no es Firefox), entonces podría iterar sobre el objeto y definirlo para un uso posterior, por ejemplo:

if (myobj.__count__ === undefined) {
  myobj.__count__ = ...
}

De esta manera, cualquier navegador compatible __count__ usaría eso, y las iteraciones solo se llevarían a cabo para aquellos que no lo hacen. Si el recuento cambia y no puede hacer esto, siempre puede hacerlo funcionar:

if (myobj.__count__ === undefined) {
  myobj.__count__ = function() { return ... }
  myobj.__count__.toString = function() { return this(); }
}

De esta manera siempre que hagas referencia a myobj.__count__ la función se disparará y volverá a calcular.


15
2018-01-17 11:15



Según lo declarado por Avi Flax https://stackoverflow.com/a/4889658/1047014

Object.keys(obj).length

hará el truco para todas las propiedades enumerables en su objeto, pero para incluir también las propiedades no enumerables, en su lugar puede usar el Object.getOwnPropertyNames. Aquí está la diferencia:

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

Como se dijo aquí esto tiene el mismo soporte de navegador que Object.keys

Sin embargo, en la mayoría de los casos, es posible que no desee incluir los no enumerables en este tipo de operaciones, pero siempre es bueno saber la diferencia;)


15
2018-03-30 01:11



Para iterar en Avi Flax, responde Object.keys (obj) .length es correcto para un objeto que no tiene funciones vinculadas a él

ejemplo:

obj = {"lol": "what", owo: "pfft"};
Object.keys(obj).length; // should be 2

versus

arr = [];
obj = {"lol": "what", owo: "pfft"};
obj.omg = function(){
    _.each(obj, function(a){
        arr.push(a);
    });
};
Object.keys(obj).length; // should be 3 because it looks like this 
/* obj === {"lol": "what", owo: "pfft", omg: function(){_.each(obj, function(a){arr.push(a);});}} */

pasos para evitar esto:

  1. no coloque funciones en un objeto que desea contar el número de teclas en

  2. use un objeto separado o cree un nuevo objeto específicamente para funciones (si desea contar cuántas funciones hay en el archivo usando Object.keys(obj).length)

También sí, utilicé el módulo _ o subrayado de nodejs en mi ejemplo

la documentación se puede encontrar aquí http://underscorejs.org/ así como su fuente en github y otra información más

Y finalmente una implementación lodash https://lodash.com/docs#size

_.size(obj)


12
2018-01-04 09:04



Para aquellos que tienen Underscore.js incluido en su proyecto, pueden hacer:

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

o estilo funcional:

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

8
2017-08-21 03:37