¿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))
?hasOwnProperty
es 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).hasOwnProperty
está disponible en todos los objetos porque es parte delObject
prototipo del, pero en el raro caso de que este método se elimine o se anule, puede obtener resultados inesperados. Al llamarlo,Object.prototype
lo hace un poco más robusto. La razón para usarlocall
es porque desea invocar el método enobj
lugar 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).length
Recomiendo 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).length
funcionó 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).length
devuelve 0.Object.keys
internamente. El subrayado también copia cada clave en una matriz dentro de unfor..in
bucle siObject.keys
no está definida.La implementación estándar de objetos ( Propiedades y métodos internos de objetos ES5.1 ) no requiere un
Object
seguimiento de su número de claves / propiedades, por lo que no debe haber una forma estándar de determinar el tamaño de unObject
sin 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
k
local (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
hasOwnProperty
mé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 myobj
aumentarí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.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;)
fuente
Object.getOwnPropertyNames
fuiste 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).length
Pero: 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.count
while(i--){...}
add
reemplaza un elemento antiguo o siremove
se llama con un índice no existente. Además, no es posible verificar si la lista tiene un índice dado siundefined
es un valor de elemento válido.Puede usar
Object.keys(data).length
para 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.Item
no 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