Número de elementos en un objeto javascript

103

¿Hay alguna manera de obtener (desde algún lugar) la cantidad de elementos en un objeto javascript? (es decir, complejidad en tiempo constante).

No puedo encontrar una propiedad o método que recupere esa información. Hasta ahora solo puedo pensar en hacer una iteración a través de toda la colección, pero eso es tiempo lineal.
Es extraño que no haya acceso directo al tamaño del objeto, ¿no crees?

EDITAR:
estoy hablando del Objectobjeto (no de los objetos en general):

var obj = new Object ;
Liberarse
fuente
5
Ya contestado aquí stackoverflow.com/questions/126100/... Object.keys (obj) .length
polainas

Respuestas:

155

Aunque las implementaciones de JS pueden realizar un seguimiento de dicho valor internamente, no existe una forma estándar de obtenerlo.

En el pasado, la variante de Javascript de Mozilla expuso el no estándar__count__ , pero se ha eliminado con la versión 1.8.5.

Para las secuencias de comandos entre navegadores, está atrapado en iterar explícitamente sobre las propiedades y verificar hasOwnProperty():

function countProperties(obj) {
    var count = 0;

    for(var prop in obj) {
        if(obj.hasOwnProperty(prop))
            ++count;
    }

    return count;
}

En el caso de implementaciones compatibles con ECMAScript 5, esto también se puede escribir como (Felicitaciones a Avi Flax )

function countProperties(obj) {
    return Object.keys(obj).length;
}

Tenga en cuenta que también perderá propiedades que no se puedan enumerar (por ejemplo, una matriz length).

Si está utilizando un marco como jQuery, Prototype, Mootools, $ cualquiera que sea el bombo más nuevo, verifique si vienen con su propia API de colecciones, que podría ser una mejor solución a su problema que usar objetos JS nativos.

Christoph
fuente
11
Maldita sea, siempre olvido hasOwnProperty. Demasiado tiempo en tierra .NET, te lo digo. +1
annakata
2
jQuery usa un objeto para sus colecciones que obtiene de las consultas y expone ese valor con una propiedad de longitud.
Nosredna
6
Firefox4 __count__se ha ido :(
Timo Huovinen
1
¿Hay alguna forma de hacer esto sin un for in? Estoy en el mismo tipo de enlace, pero me gustaría que pase JSLint si es posible.
Farola
1
¿Por qué lo necesitamos hasOwnProperty()?
swisswiss
99

Para hacer esto en cualquier entorno compatible con ES5

Object.keys(obj).length

(Soporte del navegador desde aquí )
(Doc sobre Object.keys aquí , incluye un método que puede agregar a navegadores que no son ECMA5)

ZelkiN
fuente
2
Esta no es la pregunta correcta para responder. Con eso, está tomando todas las claves del objeto, colocándolas en una matriz recién creada y luego recuperando la propiedad de longitud de esa nueva matriz.
GetFree
11
Puede que no sea el más eficaz desde el punto de vista de la programación, pero es el más eficaz para los desarrolladores.
superluminario
9

si ya está usando jQuery en su compilación, simplemente haga esto:

$(yourObject).length

Funciona muy bien para mí en objetos, y ya tenía jQuery como dependencia.

IndelebleHeff
fuente
5
Extraño ... esto no funciona para mí. Siempre obtengo 1. La respuesta de ZelkiN me funciona.
Mike Rodent
3
Este código siempre devuelve 1. Solo 1 objeto. No cuenta elementos en él
BeRocket
5
function count(){
    var c= 0;
    for(var p in this) if(this.hasOwnProperty(p))++c;
    return c;
}

var O={a: 1, b: 2, c: 3};

count.call(O);
Kennebec
fuente
2

AFAIK, no hay forma de hacer esto de manera confiable, a menos que cambie a una matriz. Lo cual, honestamente, no parece extraño, me parece bastante sencillo que las matrices son contables y los objetos no.

Probablemente lo más cerca que estarás es algo como esto

// Monkey patching on purpose to make a point
Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this ) i++;
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 3

Pero esto crea problemas, o al menos preguntas. Se cuentan todas las propiedades creadas por el usuario, incluida la función _length. Y aunque en este ejemplo simple podría evitarlo simplemente usando una función normal, eso no significa que pueda evitar que otros scripts hagan esto. ¿Entonces, Qué haces? ¿Ignorar las propiedades de la función?

Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this )
  {
      if ( 'function' == typeof this[p] ) continue;
      i++;
  }
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 2

Al final, creo que probablemente deberías deshacerte de la idea de hacer que tus objetos sean contables y encontrar otra forma de hacer lo que sea que estés haciendo.

Peter Bailey
fuente
8
¡PELIGRO SERÁ ROBINSON! ¡ NO proto contra Objeto! Todo desciende de Object, paralizará el procesamiento del cliente de esta manera si está haciendo una cantidad considerable de trabajo JS.
Annakata
5
Uh ... ¿no leíste la parte donde escribí en un comentario "Monkey parcheando a propósito para hacer un punto"? Vamos, lo hice deliberadamente para que la gente no se volviera un poco al respecto. Además, aunque no defiendo el parche de monos, malinterpreta cómo funciona la cadena de prototipos en Javascript si cree que esto causaría problemas de rendimiento video.yahoo.com/watch/111585/1027823
Peter Bailey
Entonces ... ¿esto es hacer o no?
OscarRyz
En "Javascript: The Good Parts", crea un prototipo de objeto con un método "create ()". Creo que es el libro definitivo sobre Javascript.
Chris Dutrow
1

El concepto de número / longitud / dimensionalidad realmente no tiene sentido para un Objeto, y necesitarlo sugiere que realmente quieres un Array para mí.

Editar: Me señaló que desea una O (1) para esto. Que yo sepa, me temo que no existe tal forma.

Annakata
fuente
Propuso iterar él mismo, que es esta solución. Necesitaba una forma O (1) para lograr esto ...
Thomas Hansen
Tienes toda la razón. Realmente debería leer las preguntas con más detenimiento.
Annakata
En realidad, los objetos son lo más parecido a un mapa que hay en JS. Los mapas tienen longitud.
Cristian Vrabie