¿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 __count__propiedad mágica , pero esta se eliminó en algún lugar alrededor de la versión 4.)

Respuestas:
Para hacer esto en cualquier entorno compatible con ES5 , como Node , Chrome, IE 9+, Firefox 4+ o Safari 5+:
fuente
Podrías usar este código:
Entonces puede usar esto también en navegadores antiguos:
fuente
(Object.prototype.hasOwnProperty.call(obj, k))?hasOwnPropertyes necesario verificar . Solo devuelve propiedades establecidas en el objeto mismo.obj.hasOwnProperty(k)(en realidad lo hice en mi publicación original, pero lo actualicé más tarde).hasOwnPropertyestá disponible en todos los objetos porque es parte delObjectprototipo del, pero en el raro caso de que este método se elimine o se anule, puede obtener resultados inesperados. Al llamarlo,Object.prototypelo hace un poco más robusto. La razón para usarlocalles porque desea invocar el método enobjlugar del prototipo.Si está utilizando Underscore.js puede usar _.size (gracias @douwe):
_.size(obj)Alternativamente, también puede usar _.keys que podrían ser más claros para algunos:
_.keys(obj).lengthRecomiendo mucho Underscore, es una biblioteca compacta para hacer muchas cosas básicas. Siempre que sea posible, coinciden con ECMA5 y difieren de la implementación nativa.
De lo contrario, apoyo la respuesta de @ Avi. Lo edité para agregar un enlace al documento de MDC que incluye el método de claves () que puede agregar a los navegadores que no son ECMA5.
fuente
_.keys(obj).lengthfuncionó mejor para mí, porque mi objeto de retorno es a veces una cadena simple sin propiedades dentro de él._.size(obj)me devuelve la longitud de la cadena, mientras_.keys(obj).lengthdevuelve 0.Object.keysinternamente. El subrayado también copia cada clave en una matriz dentro de unfor..inbucle siObject.keysno está definida.La implementación estándar de objetos ( Propiedades y métodos internos de objetos ES5.1 ) no requiere un
Objectseguimiento de su número de claves / propiedades, por lo que no debe haber una forma estándar de determinar el tamaño de unObjectsin iterar explícita o implícitamente sobre sus claves.Aquí están las alternativas más utilizadas:
1. Object.keys de ECMAScript ()
Object.keys(obj).length;Funciona iterando internamente sobre las teclas para calcular una matriz temporal y devuelve su longitud.2. Soluciones basadas en bibliotecas
Muchos ejemplos basados en bibliotecas en otras partes de este tema son expresiones idiomáticas útiles en el contexto de su biblioteca. Sin embargo, desde el punto de vista del rendimiento, 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 ya sea for-loop o ES5
Object.keys(nativo o shimmed).3. Optimizar un ciclo for
La parte más lenta de tal ciclo for es generalmente la
.hasOwnProperty()llamada, debido a la sobrecarga de la llamada de función. Entonces, cuando solo quiero la cantidad de entradas de un objeto JSON, simplemente salteo la.hasOwnProperty()llamada si sé que ningún código se extendió ni se extenderáObject.prototype.De lo contrario, su código podría optimizarse ligeramente haciendo
klocal (var k) y utilizando el operador de incremento de prefijo (++count) en lugar de postfix.Otra idea se basa en el almacenamiento en caché del
hasOwnPropertymétodo:Si esto es más rápido o no en un entorno determinado es una cuestión de evaluación comparativa. Se puede esperar una ganancia de rendimiento muy limitada de todos modos.
fuente
var k in myobjaumentaría el rendimiento? Hasta donde sé, solo las funciones declaran un nuevo alcance en JavaScript. ¿Los in-loops son una excepción a esta regla?for (var k in myobj) hasOwn.call(myobj, k) && ++count;es decir, reemplazar la declaración if con un simple &&?Object.getOwnPropertyNames(obj).length:; Mucho más simple.Si realmente se encuentra con un problema de rendimiento, le sugiero que ajuste las llamadas que agregan / eliminan propiedades al / del objeto con una función que también incrementa / disminuye una propiedad con el nombre apropiado (¿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. Simplemente envuelva ese bit de código en una función
getNumberOfProperties(object)y termine con él.fuente
Según lo indicado por Avi Flax https://stackoverflow.com/a/4889658/1047014
hará el truco para todas las propiedades enumerables en su objeto, pero para incluir también las propiedades no enumerables, puede usar el
Object.getOwnPropertyNames. Aquí está la diferencia:Como se indicó aquí, este tiene el mismo soporte de navegador que
Object.keysSin 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;)
fuente
Object.getOwnPropertyNamesfuiste el único aquí ...No conozco ninguna forma de hacer esto, sin embargo, para mantener las iteraciones al mínimo, podría intentar verificar la existencia de
__count__y si no existe (es decir, no Firefox), podría iterar sobre el objeto y definir para su uso posterior, por ejemplo:De esta forma, cualquier navegador compatible
__count__lo usaría, 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 podría hacerlo una función:De esta manera cada vez que haga referencia a myobj.
__count__la función se activará y volverá a calcular.fuente
Object.prototype.__count__se está eliminando en Gecko 1.9.3: whereswalden.com/2010/04/06/… cuenta -propiedad-de-objetos-se-está-eliminando /Object.__count__se ha ido, y buen viaje también.Para iterar en Avi Flax, responda Object.keys (obj) .length es correcto para un objeto que no tiene funciones vinculadas
ejemplo:
versus
pasos para evitar esto:
no coloque funciones en un objeto en el que desee contar el número de claves
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
Y finalmente una implementación lodash https://lodash.com/docs#size
_.size(obj)fuente
Array(obj).length: No funciona. http://jsfiddle.net/Jhy8M/false, aunque yo aún no he encontrado ninguna documentación sobre cómovar obj = { a: true, b: true }pueden diferir devar obj = {}; obj.a = true; obj.b = true;o simplemente si una interpretación diferente / semántica de la W3 tiene sido adoptado por Chrome.como se respondió anteriormente:
Object.keys(obj).lengthPero: como ahora tenemos una clase de Mapa real en ES6, sugeriría usarla en lugar de usar las propiedades de un objeto.
fuente
Para aquellos que tienen Underscore.js incluido en su proyecto, pueden hacer:
o estilo funcional:
fuente
Aquí hay algunas pruebas de rendimiento para tres métodos;
https://jsperf.com/get-the-number-of-keys-in-an-object
Object.keys (). Length
20,735 operaciones por segundo
Muy simple y compatible. Corre rápido pero costoso porque crea una nueva matriz de claves, que luego se descarta.
recorrer las teclas
15,734 operaciones por segundo
Ligeramente más lento, pero nada cerca del uso de memoria, por lo que probablemente sea mejor si está interesado en optimizar para dispositivos móviles u otras máquinas pequeñas
Usar mapa en lugar de objeto
953,839,338 operaciones por segundo
Básicamente, Map rastrea su propio tamaño, por lo que solo estamos devolviendo un campo numérico. Mucho, mucho más rápido que cualquier otro método. Si tiene control del objeto, conviértalos en mapas.
fuente
De: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Puedes agregarlo a todos tus objetos:
O un solo objeto:
Ejemplo:
Agregado de esa manera, no se mostrará en ... en bucles:
Salida:
Nota: no funciona en los navegadores <IE9.
fuente
Cómo he resuelto este problema es crear mi propia implementación de una lista básica que mantiene un registro de cuántos elementos están almacenados en el objeto. Es muy simple. Algo como esto:
fuente
var i = basiclist.countwhile(i--){...}addreemplaza un elemento antiguo o siremovese llama con un índice no existente. Además, no es posible verificar si la lista tiene un índice dado siundefinedes un valor de elemento válido.Puede usar
Object.keys(data).lengthpara encontrar la longitud del objeto JSON que tiene datos clavefuente
Para aquellos que tienen Ext JS 4 en su proyecto, pueden hacer:
La ventaja de esto es que funcionará en todos los navegadores compatibles con Ext (incluido IE6-IE8), sin embargo, creo que el tiempo de ejecución no es mejor que O (n), como ocurre con otras soluciones sugeridas.
fuente
Puedes usar:
y
fuente
OP no especificó si el objeto es una lista de nodos, si es así, puede usar el método de longitud directamente. Ejemplo:
fuente
Si jQuery anterior no funciona, intente
fuente
Object.Itemno existeNo creo que esto sea posible (al menos no sin usar algunos elementos internos). Y no creo que ganarías mucho optimizando esto.
fuente
Intento ponerlo a disposición de todos los objetos como este:
fuente
Google Closure tiene una buena función para esto ... goog.object.getCount (obj)
mira goog.Object Documentation
fuente