Pregunta

Si tengo un objeto JavaScript, digamos

var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;

¿Existe alguna forma de mejores prácticas incorporada o aceptada para obtener la longitud de este objeto?

¿Fue útil?

Solución

La respuesta más sólida (es decir,que captura la intención de lo que intentas hacer y al mismo tiempo causa la menor cantidad de errores) sería:

Object.size = function(obj) {
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};

// Get the size of an object
var size = Object.size(myObj);

Hay una especie de convención en JavaScript que no agregues cosas a Object.prototype, porque puede romper enumeraciones en varias bibliotecas.Sin embargo, agregar métodos a Object suele ser seguro.


Aquí hay una actualización de 2016 y implementación generalizada de ES5 y más allá. Para IE9+ y todos los demás navegadores modernos compatibles con ES5+, puede utilizar Object.keys() entonces el código anterior simplemente se convierte en:

var size = Object.keys(myObj).length;

Esto no tiene por qué modificar ningún prototipo existente ya que Object.keys() ahora está integrado.

Editar:Los objetos pueden tener propiedades simbólicas que no se pueden devolver mediante el método Object.key.Entonces la respuesta estaría incompleta sin mencionarlos.

Se agregó el tipo de símbolo al lenguaje para crear identificadores únicos para las propiedades del objeto.El principal beneficio del tipo de símbolo es la prevención de sobrescritura.

Object.keys o Object.getOwnPropertyNames no funciona para propiedades simbólicas.Para devolverlos necesitas usar Object.getOwnPropertySymbols.

var person = {
  [Symbol('name')]: 'John Doe',
  [Symbol('age')]: 33,
  "occupation": "Programmer"
};

const propOwn = Object.getOwnPropertyNames(person);
console.log(propOwn.length); // 1

let propSymb = Object.getOwnPropertySymbols(person);
console.log(propSymb.length); // 2

Otros consejos

Si sabes que no tienes que preocuparte hasOwnProperty comprobaciones, puedes hacer esto de forma muy sencilla:

Object.keys(myArray).length

Actualizado:Si estas usando Subrayado.js (recomendado, ¡es liviano!), entonces puedes hacerlo

_.size({one : 1, two : 2, three : 3});
=> 3

Si no, y no quieres perder el tiempo con las propiedades del objeto por cualquier motivo, y ya estás usando jQuery, hay un complemento igualmente accesible:

$.assocArraySize = function(obj) {
    // http://stackoverflow.com/a/6700/11236
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};

Esta es la solución más compatible con todos los navegadores.

Esto es mejor que la respuesta aceptada porque usa Object.keys nativos si existen.Por tanto, es el más rápido para todos los navegadores modernos.

if (!Object.keys) {
    Object.keys = function (obj) {
        var arr = [],
            key;
        for (key in obj) {
            if (obj.hasOwnProperty(key)) {
                arr.push(key);
            }
        }
        return arr;
    };
}

Object.keys(obj).length;

No soy un experto en JavaScript, pero parece que tendrías que recorrer los elementos y contarlos ya que Object no tiene un método de longitud:

var element_count = 0;
for (e in myArray) {  if (myArray.hasOwnProperty(e)) element_count++; }

@palmsey:Para ser justos con el OP, la documentación de JavaScript en realidad se refiere explícitamente al uso de variables de tipo Objeto de esta manera como "matrices asociativas".

Este método obtiene todos los nombres de propiedades de su objeto en una matriz, por lo que puede obtener la longitud de esa matriz que es igual a la longitud de las claves de su objeto.

Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2

Para no alterar el prototipo u otro código, puedes crear y ampliar tu propio objeto:

function Hash(){
    var length=0;
    this.add = function(key, val){
         if(this[key] == undefined)
         {
           length++;
         }
         this[key]=val;
    }; 
    this.length = function(){
        return length;
    };
}

myArray = new Hash();
myArray.add("lastname", "Simpson");
myArray.add("age", 21);
alert(myArray.length()); // will alert 2

Si siempre usa el método agregar, la propiedad de longitud será correcta.Si le preocupa que usted u otras personas se olviden de usarlo, también puede agregar el contador de propiedades que los demás han publicado en el método de longitud.

Por supuesto, siempre puedes sobrescribir los métodos.Pero incluso si lo hace, su código probablemente fallará notablemente, lo que facilitará su depuración.;)

El más simple es

Object.keys(myObject).length

Así es como se hace y no olvide verificar que la propiedad no esté en la cadena del prototipo:

var element_count = 0;
for(var e in myArray)
    if(myArray.hasOwnProperty(e))
        element_count++;

Simplemente use esto para obtener el length:

Object.keys(myObject).length

En algunos casos, es mejor simplemente almacenar el tamaño en una variable separada.Especialmente, si está agregando a la matriz un elemento en un solo lugar y puede incrementar fácilmente el tamaño.Obviamente, funcionaría mucho más rápido si necesita comprobar el tamaño con frecuencia.

Aquí hay una solución completamente diferente que solo funcionará en navegadores más modernos (IE9+, Chrome, Firefox 4+, Opera 11.60+, Safari 5.1+)

Ver jsFiddle

Configure su clase de matriz asociativa

/**
 * @constructor
 */
AssociativeArray = function () {};

// Make the length property work
Object.defineProperty(AssociativeArray.prototype, "length", {
    get: function () {
        var count = 0;
        for (var key in this) {
            if (this.hasOwnProperty(key))
                count++;
        }
        return count;
    }
});

Ahora puedes usar este código de la siguiente manera...

var a1 = new AssociativeArray();
a1["prop1"] = "test";
a1["prop2"] = 1234;
a1["prop3"] = "something else";
alert("Length of array is " + a1.length);

Usar:

var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
obj = Object.keys(myArray).length;
console.log(obj)

@palmsey:Para ser justos con el OP, los documentos de JavaScript en realidad se refieren explícitamente al uso de variables de tipo Objeto de esta manera como "matrices asociativas".

Y para ser justos con @palmsey, tenía toda la razón: no son matrices asociativas, definitivamente son objetos :) - haciendo el trabajo de una matriz asociativa.Pero en lo que respecta al punto más amplio, definitivamente parece que tienes razón según este artículo bastante bueno que encontré:

Las “matrices asociativas” de JavaScript se consideran dañinas

Pero según todo esto, ¿no es el respuesta aceptada ¿Es una mala práctica?

Especificar una función de tamaño de prototipo() para Objeto

Si se ha agregado algo más al Objeto .prototipo, el código sugerido fallará:

<script type="text/javascript">
Object.prototype.size = function () {
  var len = this.length ? --this.length : -1;
    for (var k in this)
      len++;
  return len;
}
Object.prototype.size2 = function () {
  var len = this.length ? --this.length : -1;
    for (var k in this)
      len++;
  return len;
}
var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
alert("age is " + myArray["age"]);
alert("length is " + myArray.size());
</script>

No creo que esa respuesta deba ser la aceptada, ya que no se puede confiar en que funcione si tiene algún otro código ejecutándose en el mismo contexto de ejecución.Para hacerlo de manera sólida, seguramente necesitará definir el método de tamaño dentro de myArray y verificar el tipo de miembros a medida que los recorre.

¿Qué tal algo como esto?

function keyValuePairs() {
    this.length = 0;
    function add(key, value) { this[key] = value; this.length++; }
    function remove(key) { if (this.hasOwnProperty(key)) { delete this[key]; this.length--; }}
}

Si tenemos el hash

hash = {"a":"antes de Cristo":"d"};

podemos obtener la longitud usando la longitud de las claves, que es la longitud del hash:

claves (hash). longitud

Si estas usando angularjs 1.x puedes hacer las cosas a la manera de AngularJS creando un filtro y usando el código de cualquiera de los otros ejemplos, como el siguiente:

// Count the elements in an object
app.filter('lengthOfObject', function() {
  return function( obj ) {
    var size = 0, key;
    for (key in obj) {
      if (obj.hasOwnProperty(key)) size++;
    }
   return size;
 }
})

Uso

En tu controlador:

$scope.filterResult = $filter('lengthOfObject')($scope.object)

O en tu opinión:

<any ng-expression="object | lengthOfObject"></any>

<script>
myObj = {"key1" : "Hello", "key2" : "Goodbye"};
var size = Object.keys(myObj).length;
console.log(size);
</script>

<p id="myObj">The number of <b>keys</b> in <b>myObj</b> are: <script>document.write(size)</script></p>

Esto funciona para mí:

var size = Object.keys(myObj).length;

Si necesita una estructura de datos asociativa que exponga su tamaño, es mejor utilizar un mapa en lugar de un objeto.

var myMap = new Map();
myMap.set("firstname", "Gareth");
myMap.set("lastname", "Simpson");
myMap.set("age", 21);
myMap.size; // 3

Una variación de algunos de los anteriores es:

var objLength = function(obj){    
    var key,len=0;
    for(key in obj){
        len += Number( obj.hasOwnProperty(key) );
    }
    return len;
};

Es una forma un poco más elegante de integrar hasOwnProp.

Si no le interesa admitir Internet Explorer 8 o inferior, puede obtener fácilmente la cantidad de propiedades de un objeto aplicando los dos pasos siguientes:

  1. Ejecutar cualquiera Object.keys() para obtener una matriz que contenga solo los nombres de aquellas propiedades que son enumerable o Object.getOwnPropertyNames() si desea incluir también los nombres de propiedades que no son enumerables.
  2. Consigue el .length propiedad de esa matriz.

Si necesita hacer esto más de una vez, puede incluir esta lógica en una función:

function size(obj, enumerablesOnly) {
    return enumerablesOnly === false ?
        Object.getOwnPropertyNames(obj).length :
        Object.keys(obj).length;
}

Cómo utilizar esta función en particular:

var myObj = Object.create({}, {
    getFoo: {},
    setFoo: {}
});
myObj.Foo = 12;

var myArr = [1,2,5,4,8,15];

console.log(size(myObj));        // Output : 1
console.log(size(myObj, true));  // Output : 1
console.log(size(myObj, false)); // Output : 3
console.log(size(myArr));        // Output : 6
console.log(size(myArr, true));  // Output : 6
console.log(size(myArr, false)); // Output : 7

Ver también este violín para una demostración.

var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
  1. Objeto.valores(miObjeto).longitud
  2. Objeto.entradas(miObjeto).longitud
  3. Objeto.claves(miObjeto).longitud

Aquí hay una versión diferente de la respuesta de James Cogan.En lugar de pasar un argumento, simplemente cree un prototipo de la clase Objeto y haga que el código sea más limpio.

Object.prototype.size = function () {
    var size = 0,
        key;
    for (key in this) {
        if (this.hasOwnProperty(key)) size++;
    }
    return size;
};

var x = {
    one: 1,
    two: 2,
    three: 3
};

x.size() === 3;

ejemplo de jsfiddle: http://jsfiddle.net/qar4j/1/

Puedes simplemente usar Object.keys(obj).length sobre cualquier objeto para obtener su longitud.Object.keys devuelve una matriz que contiene todo el objeto llaves (propiedades) que pueden resultar útiles para encontrar la longitud de ese objeto utilizando la longitud de la matriz correspondiente.Incluso puedes escribir un función para esto.Vamos a llegar creativo y escribe un método para ello también (junto con una propiedad getter más conveniente):

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

console.log(objLength({a:1, b:"summit", c:"nonsense"}));

// Works perfectly fine
var obj = new Object();
obj['fish'] = 30;
obj['nullified content'] = null;
console.log(objLength(obj));

// It also works your way, which is creating it using the Object constructor
Object.prototype.getLength = function() {
   return Object.keys(this).length;
}
console.log(obj.getLength());

// You can also write it as a method, which is more efficient as done so above

Object.defineProperty(Object.prototype, "length", {get:function(){
    return Object.keys(this).length;
}});
console.log(obj.length);

// probably the most effictive approach is done so and demonstrated above which sets a getter property called "length" for objects which returns the equivalent value of getLength(this) or this.getLength()

La forma más sencilla es así.

Object.keys(myobject).length

donde miobjeto es el objeto de lo que quieres la longitud

siempre puedes hacer Object.getOwnPropertyNames(myObject).length para obtener el mismo resultado que [].length daría para una matriz normal.

A continuación se muestra una versión de la respuesta de James Coglan en CoffeeScript para aquellos que han abandonado JavaScript directo :)

Object.size = (obj) ->
  size = 0
  size++ for own key of obj
  size

Propiedad

Object.defineProperty(Object.prototype, 'length', {
    get: function () {
        var size = 0, key;
        for (key in this)
            if (this.hasOwnProperty(key))
                size++;
        return size;
    }
});

Usar

var o = {a: 1, b: 2, c: 3};
alert(o.length); // <-- 3
o['foo'] = 123;
alert(o.length); // <-- 4

Podemos encontrar la longitud del objeto usando:

Object.values(myObject).length

Un poco tarde para el juego, pero una buena manera de lograr esto (solo IE9+) es definir un captador mágico en la propiedad de longitud:

Object.defineProperty(Object.prototype, "length", {
    get: function () {
        return Object.keys(this).length;
    }
});

Y puedes usarlo así:

var myObj = { 'key': 'value' };
myObj.length;

Daría 1.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top