Les propriétés dites « énumérables » sont celles pour lesquelles la caractéristique interne [[Enumerable]]
vaut true
. C'est le cas par défaut pour les propriétés qui sont créées grâce à une affectation simple ou grâce à un initialisateur de propriété. Les propriétés définies avec des méthodes analogues à Object.defineProperty()
auront [[Enumerable]]
à false
). Les propriétés énumérables sont celles qui seront parcourues dans une boucle for..in
(sauf si le nom de la propriété est un Symbol
).
Le rattachement des propriétés est détérminé selon que la propriété est directement rattachée à l'objet et non à sa chaîne de prototypes. Il est également possible de récupérer l'ensemble des propriétés d'un objet. Dans le tableau suivant, on détaille les moyens possibles pour détecter, parcourir, énumérer, récupérer les propriétés d'un objet.
Caractère énumérable et rattachement - méthodes natives pour détecter, récupérer et parcourir les propriétés
Fonctionnalité |
Rattachement direct à l'objet |
Rattachement direct à l'objet et sur la chaîne de prototypes |
Uniquement sur la chaîne de prototypes |
Détection |
|
Énumerables |
Non-énumérables |
Toutes |
Cette fonctionnalité n'est pas disponible sans code supplémentaire. |
Cette fonctionnalité n'est pas disponible sans code supplémentaire. |
in |
|
Cette fonctionnalité n'est pas disponible sans code supplémentaire. |
Récupération |
|
Cette fonctionnalité n'est pas disponible sans code supplémentaire. |
Cette fonctionnalité n'est pas disponible sans code supplémentaire. |
Parcours |
|
Énumerables |
Non-énumérables |
Toutes |
for..in |
Cette fonctionnalité n'est pas disponible sans code supplémentaire. |
Cette fonctionnalité n'est pas disponible sans code supplémentaire. |
|
Cette fonctionnalité n'est pas disponible sans code supplémentaire. |
Dans la plupart des cas, ce n'est pas l'algorithme le plus efficace mais il est présenté ici à des fins explicatives.
- On peut détecter la présence d'une propriété grâce à
RecuperateurDePropriete.laMethodeSouhaitee(obj).indexOf(prop) > -1
- On peut parcourir les propriétés souhaitées avec
RecuperateurDePropriete.laMethodeSouhaitee(obj).forEach(function (value, prop) {});
(on peut aussi utiliser filter()
, map()
, etc.)
var RecuperateurDePropriete = {
getOwnEnumerables: function (obj) {
return this._getPropertyNames(obj, true, false, this._enumerable);
},
getOwnNonenumerables: function (obj) {
return this._getPropertyNames(obj, true, false, this._notEnumerable);
},
getOwnEnumerablesAndNonenumerables: function (obj) {
return this._getPropertyNames(obj, true, false, this._enumerableAndNotEnumerable);
},
getPrototypeEnumerables: function (obj) {
return this._getPropertyNames(obj, false, true, this._enumerable);
},
getPrototypeNonenumerables: function (obj) {
return this._getPropertyNames(obj, false, true, this._notEnumerable);
},
getPrototypeEnumerablesAndNonenumerables: function (obj) {
return this._getPropertyNames(obj, false, true, this._enumerableAndNotEnumerable);
},
getOwnAndPrototypeEnumerables: function (obj) {
return this._getPropertyNames(obj, true, true, this._enumerable);
},
getOwnAndPrototypeNonenumerables: function (obj) {
return this._getPropertyNames(obj, true, true, this._notEnumerable);
},
getOwnAndPrototypeEnumerablesAndNonenumerables: function (obj) {
return this._getPropertyNames(obj, true, true, this._enumerableAndNotEnumerable);
},
_enumerable : function (obj, prop) {
return obj.propertyIsEnumerable(prop);
},
_notEnumerable : function (obj, prop) {
return !obj.propertyIsEnumerable(prop);
},
_enumerableAndNotEnumerable : function (obj, prop) {
return true;
},
_getPropertyNames : function getAllPropertyNames(obj, iterateSelfBool, iteratePrototypeBool, includePropCb) {
var props = [];
do {
if (iterateSelfBool) {
Object.getOwnPropertyNames(obj).forEach(function (prop) {
if (props.indexOf(prop) === -1 && includePropCb(obj, prop)) {
props.push(prop);
}
});
}
if (!iteratePrototypeBool) {
break;
}
iterateSelfBool = true;
} while (obj = Object.getPrototypeOf(obj));
return props;
}
};