Como posso enumerar as propriedades de um objeto JavaScript? [duplicado]
-
01-07-2019 - |
Pergunta
Esta questão já tem uma resposta aqui:
Como posso enumerar as propriedades de um objeto JavaScript?
Na verdade, eu quero listar todas as variáveis ??definidas e seus valores, mas eu aprendi que definir uma variável realmente cria uma propriedade do objeto janela.
Solução
bastante simples:
for(var propertyName in myObject) {
// propertyName is what you want
// you can get the value like this: myObject[propertyName]
}
Agora, você não terá variáveis ??particulares desta forma porque eles não estão disponíveis.
EDIT: @bitwiseplatypus é correto que a menos que você use o método hasOwnProperty()
, você vai ter propriedades que são herdadas - no entanto, eu não sei por que alguém familiarizado com a programação orientada a objetos esperaria nada menos! Normalmente, alguém que traz este acima foi sujeito a advertências de Douglas Crockford sobre este, que ainda confundem-me um pouco. Mais uma vez, a herança é uma parte normal de linguagens OO e é, portanto, parte do JavaScript, apesar de ser prototípico.
Agora, o que disse, hasOwnProperty()
é útil para filtrar, mas não precisa soar um aviso como se há algo perigoso na obtenção de propriedades herdadas.
EDIT 2: @bitwiseplatypus traz à tona a situação que ocorreria deveria propriedades alguém add / métodos para seus objetos em um ponto no tempo mais tarde do que quando você escreveu originalmente seus objetos (via seu protótipo) - embora seja verdade que isso pode causar um comportamento inesperado, eu pessoalmente não vejo isso como meu problema completamente. Apenas uma questão de opinião. Além disso, o que se eu projetar as coisas de tal maneira que eu uso protótipos durante a construção de meus objetos e ainda têm código que itera sobre as propriedades do objeto e eu quero todas as propriedades herdadas? Eu não usaria hasOwnProperty()
. Então, vamos dizer, alguém adiciona novas propriedades mais tarde. É que minha culpa se as coisas se comportam mal nesse ponto? Acho que não. Eu acho que é por isso que jQuery, como exemplo, especificou maneiras de estender como funciona (via jQuery.extend
e jQuery.fn.extend
).
Outras dicas
Use um loop for..in
para enumerar as propriedades do objeto, mas tenha cuidado. A enumeração irá retornar propriedades não apenas do objeto a ser enumerado, mas também dos protótipos de quaisquer objetos pai.
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 incluindo propriedades herdadas na sua enumeração, hasOwnProperty()
verificação:
for (var name in myObject) {
if (myObject.hasOwnProperty(name)) {
alert(name);
}
}
Editar: Não concordo com a afirmação de JasonBunting que não precisa se preocupar com enumerando as propriedades herdadas. Há é perigo em enumerar propriedades ao longo herdadas que você não está esperando, porque ele pode alterar o comportamento do seu código.
Não importa se este problema existe em outros idiomas; o fato é que ela existe, e JavaScript é particularmente vulnerável desde modificações protótipo de um objeto afeta objetos filho mesmo que essa modificação ocorre após instanciação.
É por isso que o JavaScript fornece hasOwnProperty()
, e é por isso que você deve usá-lo, a fim de garantir que o código de terceiros (ou qualquer outro código que pode modificar um protótipo) não quebrar o seu. Além de adicionar alguns bytes extras de código, não há desvantagem de usar hasOwnProperty()
.
A forma padrão, que já foi proposto várias vezes é:
for (var name in myObject) {
alert(name);
}
No entanto Internet Explorer 6, 7 e 8 têm um bug no interpretador JavaScript, que tem o efeito que algumas teclas não são enumerados. Se você executar este código:
var obj = { toString: 12};
for (var name in obj) {
alert(name);
}
Se vai alertar "12" em todos os navegadores, exceto IE. IE irá simplesmente ignorar esta chave. Os valores principais afetados são:
-
isPrototypeOf
-
hasOwnProperty
-
toLocaleString
-
toString
-
valueOf
Para ser realmente seguro no IE você tem 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]);
}
}
A boa notícia é que EcmaScript 5 define a função Object.keys(myObject)
, que retorna as chaves de um objecto como matriz e alguns navegadores (por exemplo Safari 4) já aplicá-lo.
Em navegadores modernos (ECMAScript 5) para obter todas as propriedades enumeráveis ??que você pode fazer:
Object.keys (obj) (Confira no link para obter um trecho para compatibilidade em navegadores mais antigos)
ou para obter propriedades também não enumeráveis:
Object.getOwnPropertyNames (obj)
Verifique ECMAScript mesa 5 compatibilidade
Informações adicionais: O que é um atributo enumerável?
Eu acho que um exemplo do caso que me pegou de surpresa é relevante:
var myObject = { name: "Cody", status: "Surprised" };
for (var propertyName in myObject) {
document.writeln( propertyName + " : " + myObject[propertyName] );
}
Mas para minha surpresa, a saída é
name : Cody
status : Surprised
forEach : function (obj, callback) {
for (prop in obj) {
if (obj.hasOwnProperty(prop) && typeof obj[prop] !== "function") {
callback(prop);
}
}
}
Por quê? Outro script na página ampliou o protótipo Objeto:
Object.prototype.forEach = function (obj, callback) {
for ( prop in obj ) {
if ( obj.hasOwnProperty( prop ) && typeof obj[prop] !== "function" ) {
callback( prop );
}
}
};
for (prop in obj) {
alert(prop + ' = ' + obj[prop]);
}
código JavaScript simples:
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
});
Eu achei ... for (property in object) { // do stuff }
irá listar todas as propriedades e, portanto, todas as variáveis ??declaradas globalmente sobre o objeto de janela ..
Aqui está como enumerar as propriedades do objeto:
var params = { name: 'myname', age: 'myage' }
for (var key in params) {
alert(key + "=" + params[key]);
}
Se você estiver usando a biblioteca Underscore.js , você pode usar a função chaves :
_.keys({one : 1, two : 2, three : 3});
=> ["one", "two", "three"]
dict Python tem o método 'chaves', e que é realmente útil. Eu acho que em JavaScript podemos ter algo com isto:
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: Mas a resposta de @ carlos-ruana funciona muito bem. Eu testei Object.keys (janela), eo resultado é o que eu esperava.
EDIT após 5 anos: não é boa idéia para estender Object
, porque pode entrar em conflito com outras bibliotecas que pode querer usar keys
em seus objetos e vai levar um comportamento imprevisível em seu projeto. resposta @ carlos-ruana é a maneira correta de obter as chaves de um objeto.
Se você está tentando enumerar as propriedades, a fim de escrever um novo código contra o objeto, eu recomendo usar um depurador como o Firebug para vê-los visualmente.
Outra técnica útil é usar Object.toJSON de Prototype () para serializar o objeto para JSON, que irá mostrar-lhe ambos os nomes e valores de propriedade.
var data = {name: 'Violet', occupation: 'character', age: 25, pets: ['frog', 'rabbit']};
Object.toJSON(data);
//-> '{"name": "Violet", "occupation": "character", "age": 25, "pets": ["frog","rabbit"]}'
Eu ainda sou um novato em JavaScript, mas eu escrevi uma pequena função para imprimir recursivamente todas as propriedades de um objeto e seus filhos:
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;
}