2008-09-17 26 views
553

¿Cómo enumero las propiedades de un objeto JavaScript?¿Cómo enumero las propiedades de un objeto JavaScript?

De hecho, quiero enumerar todas las variables definidas y sus valores, pero he aprendido que la definición de una variable realmente crea una propiedad del objeto de la ventana.

+1

La fecha no importa al elegir duplicados. La mejor pregunta permanece abierta, la otra se cierra como el duplicado. – meagar

Respuesta

714

bastante simple:

for(var propertyName in myObject) { 
    // propertyName is what you want 
    // you can get the value like this: myObject[propertyName] 
} 

Ahora, usted no conseguirá variables privadas de esta manera debido a que no están disponibles.


EDIT: @bitwiseplatypus es correcto que a menos que utilice el método hasOwnProperty(), obtendrá propiedades heredadas - sin embargo, yo no sé por qué cualquiera que esté familiarizado con la programación orientada a objetos se puede esperar nada menos! Normalmente, alguien que plantea esto ha sido objeto de las advertencias de Douglas Crockford sobre esto, que todavía me confunden un poco. Una vez más, la herencia es una parte normal de los lenguajes OO y, por lo tanto, es parte de JavaScript, a pesar de ser prototípico.

Ahora, dicho esto, hasOwnProperty() es útil para el filtrado, pero no es necesario para que suene como una advertencia si hay algo peligroso en conseguir las propiedades heredadas.

EDIT 2: @bitwiseplatypus trae a colación la situación que ocurriría si alguien agregara propiedades/métodos a sus objetos en un momento posterior al que originalmente escribió sus objetos (a través de su prototipo) - si bien es cierto que esto podría causa un comportamiento inesperado, personalmente no lo veo como mi problema por completo. Solo una cuestión de opinión. Además, ¿qué pasa si diseño las cosas de tal manera que utilizo prototipos durante la construcción de mis objetos y aún tengo un código que itera sobre las propiedades del objeto y quiero todas las propiedades heredadas? No usaría hasOwnProperty(). Entonces, digamos, alguien agrega nuevas propiedades más tarde. ¿Es culpa mía si las cosas se comportan mal en ese punto? No lo creo. Creo que esta es la razón por la que jQuery, como ejemplo, ha especificado formas de ampliar cómo funciona (a través de jQuery.extend y jQuery.fn.extend).

+7

Creo que @bitwiseplatypus solo dice "tenga cuidado". En mi opinión, el for/in de JavaScript solo debe enseñarse acompañado por una mención de hasOwnProperty() y otros casos límite menos evidentes de herencia prototípica. – pcorcoran

+0

Curiosamente, esto no funciona para las propiedades getter definidas con Object.defineProperty pero funciona para getters directos. Ver mi [jsfiddle] (http://jsfiddle.net/Sgf8N/4/). – Ciantic

+25

Creo que * la mayoría * de la gente se sorprende de que 'for (x en {})' enumere cualquier cosa, ya que parece una simple iteración de tecla del diccionario. Es muy inesperado y definitivamente merece una advertencia especial. –

9

me pareció ... for (property in object) { // do stuff } una lista de todas las propiedades, y por lo tanto todo el declarados globalmente variables en el objeto de la ventana ..

203

utilizar un bucle for..in para enumerar las propiedades de un objeto, pero tenga cuidado. La enumeración devolverá propiedades no solo del objeto que se enumera, sino también de los prototipos de cualquier objeto principal.

var myObject = {foo: 'bar'}; 

for (var name in myObject) { 
    alert(name); 
} 

// results in a single alert of 'foo' 

Object.prototype.baz = 'quux'; 

for (var name in myObject) { 
    alert(name); 
} 

// results in two alerts, one for 'foo' and one for 'baz' 

Para evitar la inclusión de las propiedades heredadas en su enumeración, comprobar hasOwnProperty():

for (var name in myObject) { 
    if (myObject.hasOwnProperty(name)) { 
    alert(name); 
    } 
} 

Editar: no estoy de acuerdo con la declaración de JasonBunting que no es necesario preocuparse por la enumeración de las propiedades heredadas. Hay es peligro en la enumeración de propiedades heredadas que no está esperando, ya que puede cambiar el comportamiento de su código.

No importa si este problema existe en otros idiomas; el hecho es que existe, y JavaScript es particularmente vulnerable ya que las modificaciones al prototipo de un objeto afectan a los objetos secundarios incluso si la modificación tiene lugar después de la creación de instancias.

Es por eso que JavaScript proporciona hasOwnProperty(), y esta es la razón por la que debe usarlo para asegurarse de que el código de terceros (o cualquier otro código que pueda modificar un prototipo) no rompa el suyo. Además de agregar algunos bytes adicionales de código, no hay inconveniente en usar hasOwnProperty().

+4

Los devotos de hasOwnProperty suelen ser aquellos que: a) han sufrido de bibliotecas comunes agresivas [por ejemplo: Prototype.js alrededor de 2003], o b) bases creadas para sistemas heterogéneos (piense en portales web). Todos los demás deberían envolver hasOwnProperty en un patrón de iterador y salir a tomar cerveza. – pcorcoran

+4

Volví a subir esto, porque usar hasOwnProperty es un complemento útil para el ciclo for, aunque no lo necesitaba en ese momento. – davenpcj

+25

Este patrón es necesario y se utiliza porque javascript combina los "Objetos del actor" con "Tablas hash". cuando el objeto es una * descripción de comportamientos y rasgos *, entonces se aplican las reglas habituales, usted desea conocer las propiedades del objeto sin preocuparse por cómo llegaron allí. Si, por otro lado, usa el objeto como un almacén de valores-clave, entonces lo más probable es que solo esté interesado en las claves reales que en realidad están almacenadas en el objeto. Otras propiedades son coincidentes y no representan el estado real del objeto. Otros idiomas resuelven esta distinción con distintos tipos. – SingleNegationElimination

0

Si está tratando de enumerar las propiedades para escribir código nuevo contra el objeto, le recomendaría usar un depurador como Firebug para verlas visualmente.

Otra técnica útil es usar Object.toJSON() de Prototype para serializar el objeto a JSON, que le mostrará los nombres de propiedades y valores.

var data = {name: 'Violet', occupation: 'character', age: 25, pets: ['frog', 'rabbit']}; 
Object.toJSON(data); 
//-> '{"name": "Violet", "occupation": "character", "age": 25, "pets": ["frog","rabbit"]}' 

http://www.prototypejs.org/api/object/tojson

13
for (prop in obj) { 
    alert(prop + ' = ' + obj[prop]); 
} 
+0

La mejor respuesta simple que explica todo lo necesario para el uso básico. – TetraDev

22

Creo que un ejemplo del caso que me ha cogido por sorpresa es relevante:

var myObject = { name: "Cody", status: "Surprised" }; 
for (var propertyName in myObject) { 
    document.writeln(propertyName + " : " + myObject[propertyName]); 
} 

Pero para mi sorpresa, la salida es

name : Cody 
status : Surprised 
forEach : function (obj, callback) { 
    for (prop in obj) { 
     if (obj.hasOwnProperty(prop) && typeof obj[prop] !== "function") { 
      callback(prop); 
     } 
    } 
} 

¿Por qué? Otra secuencia de comandos en la página se ha extendido el prototipo del objeto:

Object.prototype.forEach = function (obj, callback) { 
    for (prop in obj) { 
    if (obj.hasOwnProperty(prop) && typeof obj[prop] !== "function") { 
     callback(prop); 
    } 
    } 
}; 
+0

Interesante, supongo que eso significa que es posible NO invocar la devolución de llamada al redefinir la función forEach, lo que podría hacer que la enumeración de las propiedades se rompa. – davenpcj

+0

Sí, mi punto es que otro script podría haber agregado algo al prototipo del objeto. Ese tipo de cambios pueden estar allí, es posible que no, y los métodos agregados pueden hacer cualquier cosa. No reclamo este ejemplo de forEach is good - algo que un script podría hacer y que modificaría los resultados de for ... in para otros scripts. – cyberhobo

+0

A la luz de las tendencias modernas en el desarrollo de JavaScript, la modificación del prototipo de cualquiera de los tipos base me parece una mala decisión; hay otras formas de despellejar a la mayoría de los gatos que impulsan a las personas a hacerlo en primer lugar. –

48

La manera estándar, que ya ha sido propuesto varias veces es:

for (var name in myObject) { 
    alert(name); 
} 

Sin embargo Internet Explorer 6, 7 y 8 tienen un error en el intérprete de JavaScript, que tiene el efecto de que algunas claves no están enumeradas. Si ejecuta este código:

var obj = { toString: 12}; 
for (var name in obj) { 
    alert(name); 
} 

Si alertará "12" en todos los navegadores, excepto en IE. IE simplemente ignorará esta clave. Los valores de las claves afectadas son:

  • isPrototypeOf
  • hasOwnProperty
  • toLocaleString
  • toString
  • valueOf

Para ser realmente segura en el IE tiene que usar algo como:

for (var key in myObject) { 
    alert(key); 
} 

var shadowedKeys = [ 
    "isPrototypeOf", 
    "hasOwnProperty", 
    "toLocaleString", 
    "toString", 
    "valueOf" 
]; 
for (var i=0, a=shadowedKeys, l=a.length; i<l; i++) { 
    if map.hasOwnProperty(a[i])) { 
    alert(a[i]); 
    } 
} 

La buena noticia es que EcmaScript 5 define la función Object.keys(myObject), que devuelve las claves de un objeto como matriz y algunos navegadores (p. Safari 4) ya lo implementa.

+1

Gracias Fabian. Esta es una respuesta muy completa. –

9

simple código JavaScript:

for(var propertyName in myObject) { 
    // propertyName is what you want. 
    // You can get the value like this: myObject[propertyName] 
} 

jQuery:

jQuery.each(obj, function(key, value) { 
    // key is what you want. 
    // The value is in: value 
}); 
7

Si está utilizando la biblioteca Underscore.js, puede utilizar la función keys:

_.keys({one : 1, two : 2, three : 3}); 
=> ["one", "two", "three"] 
6

Aquí está cómo enumerar una propiedades del objeto:

var params = { name: 'myname', age: 'myage' } 

for (var key in params) { 
    alert(key + "=" + params[key]); 
} 
39

En los navegadores modernos (ECMAScript 5) para obtener todas las propiedades enumerables que puede hacer:

Object.keys(obj) (Compruebe el enlace para obtener un fragmento de compatibilidad con versiones anteriores de los navegadores antiguos)

o para obtener propiedades también no enumerables:

Object.getOwnPropertyNames(obj)

Check ECMAScript 5 compatibility table

Otros detalles: What is a enumerable attribute?

+0

'Object.getOwnPropertyNames (obj)' es lo que desea si está tratando con algún tipo de objeto Error (por ejemplo, TypeError) porque las propiedades no son enumerables. – vossad01

5

dict de Python tiene método 'claves', y que es realmente útil. Creo que en JavaScript que podemos tener algo esto:

function keys(){ 
    var k = []; 
    for(var p in this) { 
     if(this.hasOwnProperty(p)) 
      k.push(p); 
    } 
    return k; 
} 
Object.defineProperty(Object.prototype, "keys", { value : keys, enumerable:false }); 

EDIT: Pero la respuesta de @ carlos-ruana funciona muy bien. Probé Object.keys (ventana), y el resultado es lo que esperaba.

0

Puede usar el for de loop.

Si desea utilizar una matriz Object.keys (objeto1)

0

todavía soy un principiante en JavaScript, pero escribí una pequeña función para imprimir de forma recursiva todas las propiedades de un objeto y sus hijos:

getDescription(object, tabs) { 
    var str = "{\n"; 
    for (var x in object) { 
     str += Array(tabs + 2).join("\t") + x + ": "; 
     if (typeof object[x] === 'object' && object[x]) { 
     str += this.getDescription(object[x], tabs + 1); 
     } else { 
     str += object[x]; 
     } 
     str += "\n"; 
    } 
    str += Array(tabs + 1).join("\t") + "}"; 
    return str; 
} 
Cuestiones relacionadas