En fait, je veux énumérer toutes les variables définies et leurs valeurs, mais j'ai appris que la définition d'une variable crée en fait une propriété de l'objet fenêtre.
- Boucle grâce à l'objet JavaScript (5 réponses )
Réponses
Trop de publicités?C'est assez simple :
for(var propertyName in myObject) {
// propertyName is what you want
// you can get the value like this: myObject[propertyName]
}
Vous n'obtiendrez pas de variables privées de cette façon, car elles ne sont pas disponibles.
EDIT : @bitwiseplatypus Il est vrai que si vous n'utilisez pas le hasOwnProperty()
vous obtiendrez des propriétés héritées - cependant, je ne vois pas pourquoi une personne familière avec la programmation orientée objet s'attendrait à autre chose ! Généralement, les personnes qui soulèvent cette question ont été soumises aux avertissements de Douglas Crockford à ce sujet, ce qui me laisse encore un peu perplexe. Encore une fois, l'héritage est un élément normal des langages OO et fait donc partie de JavaScript, même s'il est prototypique.
Maintenant, cela dit, hasOwnProperty()
est utile pour le filtrage, mais nous n'avons pas besoin de lancer un avertissement comme s'il y avait quelque chose de dangereux à obtenir des propriétés héritées.
EDIT 2 : @bitwiseplatypus évoque la situation qui se produirait si quelqu'un ajoutait des propriétés/méthodes à vos objets à un moment ultérieur à celui où vous avez écrit vos objets à l'origine (via leur prototype) - s'il est vrai que cela pourrait provoquer un comportement inattendu, je ne considère pas personnellement que c'est entièrement mon problème. C'est juste une question d'opinion. De plus, que se passe-t-il si je conçois les choses de telle sorte que j'utilise des prototypes pendant la construction de mes objets et que j'ai pourtant du code qui itère sur les propriétés de l'objet et que je veux toutes les propriétés héritées ? Je n'utiliserais pas hasOwnProperty()
. Puis, disons que quelqu'un ajoute de nouvelles propriétés plus tard. Est-ce ma faute si les choses se comportent mal à ce moment-là ? Je ne le pense pas. Je pense que c'est la raison pour laquelle jQuery, par exemple, a spécifié des moyens d'étendre son fonctionnement (par l'intermédiaire de jQuery.extend
et jQuery.fn.extend
).
Utilisez un for..in
pour énumérer les propriétés d'un objet, mais faites attention. L'énumération renverra les propriétés non seulement de l'objet en cours d'énumération, mais aussi des prototypes de tout objet parent.
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'
Pour éviter d'inclure des propriétés héritées dans votre énumération, vérifiez hasOwnProperty()
:
for (var name in myObject) {
if (myObject.hasOwnProperty(name)) {
alert(name);
}
}
Edit : Je ne suis pas d'accord avec l'affirmation de JasonBunting selon laquelle nous n'avons pas besoin de nous soucier de l'énumération des propriétés héritées. Il y a est Il est dangereux d'énumérer des propriétés héritées que vous n'attendez pas, car cela peut modifier le comportement de votre code.
Peu importe que ce problème existe dans d'autres langages ; le fait est qu'il existe, et JavaScript est particulièrement vulnérable puisque les modifications apportées au prototype d'un objet affectent les objets enfants même si la modification a lieu après l'instanciation.
C'est pourquoi JavaScript fournit hasOwnProperty()
C'est pourquoi vous devez l'utiliser afin de vous assurer que le code d'un tiers (ou tout autre code susceptible de modifier un prototype) ne casse pas le vôtre. En dehors de l'ajout de quelques octets de code supplémentaires, il n'y a aucun inconvénient à utiliser la fonction hasOwnProperty()
.
Dans les navigateurs modernes (ECMAScript 5) pour obtenir toutes les propriétés énumérables, vous pouvez faire :
Objet.keys(obj) (Vérifiez le lien pour obtenir un extrait pour la rétrocompatibilité sur les anciens navigateurs).
Ou pour obtenir également des propriétés non dénombrables :
Object.getOwnPropertyNames(obj)
Vérifier la table de compatibilité ECMAScript 5
Informations supplémentaires : Qu'est-ce qu'un attribut énumérable ?
La méthode standard, qui a déjà été proposée à plusieurs reprises, est la suivante :
for (var name in myObject) {
alert(name);
}
Toutefois, Internet Explorer 6, 7 et 8 présente un bogue dans l'interpréteur JavaScript, qui a pour effet que certaines clés ne sont pas énumérées. Si vous exécutez ce code :
var obj = { toString: 12};
for (var name in obj) {
alert(name);
}
If alertera "12" dans tous les navigateurs sauf IE. IE ignorera simplement cette clé. Les valeurs de clé concernées sont :
isPrototypeOf
hasOwnProperty
toLocaleString
toString
valueOf
Pour être vraiment sûr dans IE, vous devez utiliser quelque chose comme :
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 bonne nouvelle, c'est qu'EcmaScript 5 définit la fonction Object.keys(myObject)
qui renvoie les clés d'un objet sous forme de tableau. Certains navigateurs (par exemple Safari 4) l'implémentent déjà.
Je pense qu'un exemple de cas qui m'a pris par surprise est pertinent :
var myObject = { name: "Cody", status: "Surprised" };
for (var propertyName in myObject) {
document.writeln( propertyName + " : " + myObject[propertyName] );
}
Mais à ma grande surprise, la sortie est
name : Cody
status : Surprised
forEach : function (obj, callback) {
for (prop in obj) {
if (obj.hasOwnProperty(prop) && typeof obj[prop] !== "function") {
callback(prop);
}
}
}
Pourquoi ? Un autre script sur la page a étendu le prototype Object :
Object.prototype.forEach = function (obj, callback) {
for ( prop in obj ) {
if ( obj.hasOwnProperty( prop ) && typeof obj[prop] !== "function" ) {
callback( prop );
}
}
};