¿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 propiedad magic __count__
, pero se eliminó en algún lugar alrededor de la versión 4.)
19 answers
Para hacer esto en cualquier entorno compatible con ES5, como Node , Chrome, IE 9+ , FF 4+ o Safari 5+:
Object.keys(obj).length
- compatibilidad del Navegador
-
Objeto.documentación de claves
- (incluye un método que puede agregar a navegadores que no son ECMA5)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-23 12:59:37
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 antiguos:
var len = Object.keys(obj).length;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-22 10:31:52
Si está utilizando Subrayado.js puedes usar _.tamaño (gracias @douwe):_.size(obj)
Alternativamente, también puede usar _.teclas que podrían ser más claras para algunos:_.keys(obj).length
Recomiendo encarecidamente Underscore, es una biblioteca apretada para hacer muchas cosas básicas. Siempre que sea posible, coinciden con ECMA5 y se remiten 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() puede agregar a navegadores que no son ECMA5.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-26 22:17:10
La implementación de Objetos estándar (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 un Object
sin iterar explícita o implícitamente sobre sus claves.
Así que aquí están las alternativas más utilizadas:
1. Objeto de ECMAScript.keys ()
Object.keys(obj).length;
Funciona por internamente iterando sobre las claves para calcular un matriz temporal y devuelve su longitud.
- Pros - Sintaxis legible y limpia. No se requiere biblioteca o código personalizado, excepto un shim si el soporte nativo no está disponible
- Cons - Sobrecarga de memoria debido a la creación del array.
2. Soluciones basadas en bibliotecas
Muchos ejemplos basados en bibliotecas en otras partes 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 comparado con un código perfecto sin biblioteca, ya que todos esos métodos de biblioteca encapsulan un bucle for o ES5 Object.keys
(nativo o shimmed).
3. Optimización de un bucle for
La parte más lenta de tal bucle for es generalmente la llamada .hasOwnProperty()
, debido a la sobrecarga de la llamada a la función. Así que cuando solo quiero el número de entradas de un objeto JSON, simplemente omito la llamada .hasOwnProperty()
si sé que ningún código hizo ni extenderá Object.prototype
.
De lo contrario, su código podría ser muy ligeramente optimizado haciendo k
local (var k
) y usando el operador de incremento de prefijo (++count
) en lugar de postfijo.
var count = 0;
for (var k in myobj) if (myobj.hasOwnProperty(k)) ++count;
Otra idea se basa en el almacenamiento en caché del método hasOwnProperty
:
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 entorno dado es una cuestión de benchmarking. De todos modos, se puede esperar una ganancia de rendimiento muy limitada.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-27 13:14:11
Si en realidad se encuentra con un problema de rendimiento, le sugeriría envolver las llamadas que agregan/eliminan propiedades al objeto con una función que también incrementa/decrementa un nombre apropiado (size?) propiedad.
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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-11 18:42:43
No estoy al tanto de ninguna manera 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), entonces podría iterar sobre el objeto y definirlo para su uso posterior, por ejemplo:
if (myobj.__count__ === undefined) {
myobj.__count__ = ...
}
De esta manera cualquier navegador que soporte __count__
usaría eso, y las iteraciones solo se llevarían a cabo para aquellos que no lo hacen. Si el conteo cambia y no puede hacer esto, siempre podría hacerlo una función:
if (myobj.__count__ === undefined) {
myobj.__count__ = function() { return ... }
myobj.__count__.toString = function() { return this(); }
}
De esta manera cada vez que haga referencia a myobj.__count__
la función se disparará y recalculará.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 09:36:59
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, puede usar 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 indica aquí {[6] } 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 numerables en este tipo de operaciones, pero siempre es bueno saber la diferencia ;)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:39
Para iterar en el objeto de respuesta Avi Flax.llaves (obj).la longitud es correcta para un objeto que no tiene funciones atadas 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:
-
No ponga funciones en un objeto en el que desee contar el número de teclas en
Utilice un objeto separado o cree un nuevo objeto específicamente para funciones (si desea contar cuántas funciones hay en el archivo utilizando
Object.keys(obj).length
)
También usé el módulo _ o underscore 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 de lodash https://lodash.com/docs#size
_.size(obj)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-02 11:44:15
Para aquellos que tienen Subrayado.js incluido en su proyecto se puede hacer:
_({a:'', b:''}).size() // => 2
O estilo funcional:
_.size({a:'', b:''}) // => 2
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-04 09:04:06
De: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Objeto.defineProperty (obj, prop, descriptor)
Puedes añadirlo a todos tus objetos:
Object.defineProperty(Object.prototype, "length", {
enumerable: false,
get: function() {
return Object.keys(this).length;
}
});
O un solo objeto:
var myObj = {};
Object.defineProperty(myObj, "length", {
enumerable: false,
get: function() {
return Object.keys(this).length;
}
});
Ejemplo:
var myObj = {};
myObj.name = "John Doe";
myObj.email = "[email protected]";
myObj.length; //output: 2
Añadido de esa manera, no se mostrará en for..in bucles:
for(var i in myObj) {
console.log(i + ":" + myObj[i]);
}
Salida:
name:John Doe
email:[email protected]
Nota: no funciona en navegadores
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-21 03:44:11
Cómo he resuelto este problema es construir mi propia implementación de una lista básica que mantiene un registro de cuántos elementos se almacenan en el objeto. Es muy simple. Algo como esto:
function BasicList()
{
var items = {};
this.count = 0;
this.add = function(index, item)
{
items[index] = item;
this.count++;
}
this.remove = function (index)
{
delete items[index];
this.count--;
}
this.get = function(index)
{
if (undefined === index)
return items;
else
return items[index];
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-18 18:09:38
Para aquellos que tienen Ext JS 4 en su proyecto puedes hacer:
Ext.Object.getSize(myobj);
La ventaja de esto es que funcionará en todos los navegadores compatibles con Ext (IE6-IE8 incluido), sin embargo, creo que el tiempo de ejecución no es mejor que O(n), al igual que con otras soluciones sugeridas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-18 16:23:26
Como se respondió anteriormente: Object.keys(obj).length
Pero: como ahora tenemos una clase real Map en ES6, yo sugeriría usarla en lugar de usar las propiedades de un objeto.
const map = new Map();
map.set("key", "value");
map.size; // THE fastest way
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-19 13:26:32
No creo que esto sea posible (al menos no sin usar algunos elementos internos). Y no creo que ganarías mucho optimizando esto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 09:05:38
Si jQuery anterior no funciona, intente
$(Object.Item).length
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-02 06:03:44
Trato de hacerlo disponible para todos los objetos de esta manera:
Object.defineProperty(Object.prototype, "length", {
get() {
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;
};
}
return Object.keys(this).length;
},});
console.log({"Name":"Joe","Age":26}.length) //returns 2
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-14 12:51:03
Puede usar Object.keys(data).length
para encontrar la longitud del objeto JSON que tiene datos clave
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-10 08:26:20
Google Closure tiene una buena función para esto... goog.objeto.getCount (obj)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-13 14:04:04
Puede utilizar:
Object.keys(objectName).length;
& Object.values(objectName).length;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-28 07:09:18