Rattachement et caractère énumérable des propriétés

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.

Property enumerability and ownership - built-in methods of detection, retrieval, and iteration
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
Énumérables Non-énumérables Toutes

propertyIsEnumerable()

hasOwnProperty()

hasOwnProperty() - en utilisant propertyIsEnumerable() afin d'exclure les propriétés énumérables hasOwnProperty()
Cette fonctionnalité n'est pas disponible sans code supplémentaire. Cette fonctionnalité n'est pas disponible sans code supplémentaire.
Récupération
Énumérables Non-énumérables Toutes

Object.keys()

getOwnPropertyNames()

getOwnPropertyNames() - en utilisant propertyIsEnumerable() afin d'exclure les propriétés énumérables getOwnPropertyNames()
Cette fonctionnalité n'est pas disponible sans code supplémentaire. Cette fonctionnalité n'est pas disponible sans code supplémentaire.
Parcours
Énumérables Non-énumérables Toutes

Object.keys()

getOwnPropertyNames()

getOwnPropertyNames() - en utilisant propertyIsEnumerable() afin d'exclure les propriétés énumérables getOwnPropertyNames()
É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.

Obtenir les propriétés selon leur caractère énumérable et selon leur rattachement

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); 
         // On pourrait également utiliser for..in qu'on filtre avec hasOwnProperty 
         // ou encore : return Object.keys(obj);
    },
    getOwnNonenumerables: function (obj) {
        return this._getPropertyNames(obj, true, false, this._notEnumerable);
    },
    getOwnEnumerablesAndNonenumerables: function (obj) {
        return this._getPropertyNames(obj, true, false, this._enumerableAndNotEnumerable); 
        // On peut également simplement utiliser : return Object.getOwnPropertyNames(obj);
    },
    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); 
        // On pourra aussi utiliser for..in sans filtre
    },
    getOwnAndPrototypeNonenumerables: function (obj) {
        return this._getPropertyNames(obj, true, true, this._notEnumerable);
    },
    getOwnAndPrototypeEnumerablesAndNonenumerables: function (obj) {
        return this._getPropertyNames(obj, true, true, this._enumerableAndNotEnumerable);
    },
    // Fonctions de rappels statiques
    _enumerable : function (obj, prop) {
        return obj.propertyIsEnumerable(prop);
    },
    _notEnumerable : function (obj, prop) {
        return !obj.propertyIsEnumerable(prop);
    },
    _enumerableAndNotEnumerable : function (obj, prop) {
        return true;
    },
    // Inspirée par https://stackoverflow.com/a/8024294/271577
    _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;
    }
};

Tableau de détection

  in for..in obj.hasOwnProperty() obj.propertyIsEnumerable() Object.keys() Object.getOwnPropertyNames() Object.getOwnPropertyDescriptors() Reflect.ownKeys()
Propriétés énumérables true true true true true true true true
Propriétés non-énumérables true false true false false true true true
Propriétés dont les clés sont des symboles true false true false false false true true
Propriétés héritées et énumérables true true false false false false false false
Propriétés héritées et non-énumérables true false false false false false false false
Propriétés héritées dont les clés sont des symboles true false false false false false false false

Voir aussi

Étiquettes et contributeurs liés au document

Étiquettes : 
 Contributeurs à cette page : SphinxKnight
 Dernière mise à jour par : SphinxKnight,