mozilla
Vos résultats de recherche

    Exemples supplémentaires pour Object.defineProperty

    Cette page illustre des exemples supplémentaires pour la méthode Object.defineProperty().

    Utiliser des masques binaires (plutôt qu'un descripteur de propriété)

    Si l'on souhaite définir de nombreuses propriétés via la méthode Object.defineProperty() , on peut utiliser le même descripteur pour chaque propriété en le modifiant chaque fois que c'est nécessaire avec des marqueurs binaires (flags) pour former un masque binaire.

    var oDesc = {};
    function defProp (nMask, oObj, sKey, vVal_fGet, fSet) {
      if (nMask & 8) {
        // descripteur d'accesseur
        if (vVal_fGet) {
          oDesc.get = vVal_fGet;
        } else {
          delete oDesc.get;
        }
        if (fSet) {
          oDesc.set = fSet;
        } else {
          delete oDesc.set;
        }
        delete oDesc.value;
        delete oDesc.writable;
      } else {
        // descripteur de données
        if (arguments.length > 3) {
          oDesc.value = vVal_fGet;
        } else {
          delete oDesc.value;
        }
        oDesc.writable = Boolean(nMask & 4);
        delete oDesc.get;
        delete oDesc.set;
      }
      oDesc.enumerable = Boolean(nMask & 1);
      oDesc.configurable = Boolean(nMask & 2);
      Object.defineProperty(oObj, sKey, oDesc);
      return oObj;
    }
    
    /*
    * :: function defProp ::
    *
    * nMask est un masque binaire:
    *  flag 0x1 : la propriété est enumérable,
    *  flag 0x2 : la propriété est configurable,
    *  flag 0x4 : la propriété est accessible en écriture,
    *  flag 0x8 : la propriété est un descripteur d'accesseur.
    * oObj est le nom de l'objet dont on souhaite définir la propriété;
    * sKey est le nom de la propriété à créer ou modifier;
    * vVal_fGet est la valeur à affecter pour un descripteur de donnée ou l'accesseur à utiliser pour un descripteur d'accesseur (selon le masque choisi)
    * fSet est le mutateur à affecter pour un descripteur d'accesseur;
    *
    * Les valeurs possibles du masque binaire :
    *
    *  0  : descripteur de données en lecture seule - non configurable, non énumérable (0000).
    *  1  : descripteur de données en lecture seule - non configurable, énumérable (0001).
    *  2  : descripteur de données en lecture seule - configurable, non énumérable (0010).
    *  3  : descripteur de données en lecture seule - configurable, énumérable (0011).
    *  4  : descripteur de données en écriture - non configurable, non énumérable (0100).
    *  5  : descripteur de données en écriture - non configurable, énumérable (0101).
    *  6  : descripteur de données en écriture - configurable, non énumérable (0110).
    *  7  : descripteur de données en écriture - configurable, énumérable (0111).
    *  8  : descripteur d'accessseur - non configurable, non énumérable (1000).
    *  9  : descripteur d'accessseur - non configurable, énumérable (1001).
    *  10 : descripteur d'accessseur - configurable, non énumérable (1010).
    *  11 : descripteur d'accessseur - configurable, énumérable (1011).
    *
    *  Note : Si le flag 0x8 est mis à "descripteur d'accesseur" le flag 0x4 (writable)
    *  sera ignoré. Sinon, l'argument fSet sera ignoré.
    */
    
    // créer un nouvel objet
    var myObj = {};
    
    // ajouter un descripteur de données en écriture - non configurable, non énumérable
    defProp(4, myObj, "myNumber", 25);
    
    // ajouter un descripteur de données en lecture seule - non configurable, énumérable
    defProp(1, myObj, "myString", "Hello world!");
    
    // ajouter un descripteur d'accesseur - non configurable, énumérable
    defProp(9, myObj, "myArray", function() {
      for (var iBit = 0, iFlag = 1, aBoolArr = [false];
            iFlag < this.myNumber + 1 || (this.myNumber & iFlag); iFlag = iFlag << 1) {
        aBoolArr[iBit++] = Boolean(this.myNumber & iFlag);
      }
      return aBoolArr;
    }, function(aNewMask) {
      for (var nNew = 0, iBit = 0; iBit < aNewMask.length; iBit++) {
        nNew |= Boolean(aNewMask[iBit]) << iBit;
      }
      this.myNumber = nNew;
    });
    
    // ajouter une descripteur de données en écriture (undefined) - configurable, énumérable
    defProp(7, myObj, "myUndefined");
    
    // ajouter un descripteur d'accesseur (uniquement le getter) - configurable, énumérable
    defProp(11, myObj, "myDate", function() { return new Date(); });
    
    // ajouter un descripteur d'accesseur (uniquement le setter) - non configurable, non énumérable
    defProp(8, myObj, "myAlert", null, function(sTxt) { alert(sTxt); });
    
    myObj.myAlert = myObj.myDate.toLocaleString() + "\n\n" + myObj.myString +
          "\nLe nombre " + myObj.myNumber + " représente le masque binaire : " +
          myObj.myArray.join(", ") + ".";
    
    // on liste les propriétés énumérables 
    var sList = "Voici les propriétés énumérables de l'objet :\n";
    for (var sProp in myObj) {
        sList += "\nmyObj." + sProp + " => " + myObj[sProp] + ";"
    }
    
    console.log(sList);
    

    Créer une nouvelle méthode Object.setProperty() non native

    On peut faire la même chose avec un descripteur d'objet obtenu via un constructeur en utilisant une méthode adaptée de Object qu'on peut appeler setProperty() :

    // créer une nouvelle méthode de Object appelée Object.setProperty()
    
    new (function() {
      var oDesc = this;
      Object.setProperty = function (nMask, oObj, sKey, vVal_fGet, fSet) {
        if (nMask & 8) {
          // accessor descriptor
          if (vVal_fGet) {
            oDesc.get = vVal_fGet;
          } else {
            delete oDesc.get;
          }
          if (fSet) {
            oDesc.set = fSet;
          } else {
            delete oDesc.set;
          }
          delete oDesc.value;
          delete oDesc.writable;
        } else {
          // data descriptor
          if (arguments.length > 3) {
            oDesc.value = vVal_fGet;
          } else {
            delete oDesc.value;
          }
          oDesc.writable = Boolean(nMask & 4);
          delete oDesc.get;
          delete oDesc.set;
        }
        oDesc.enumerable = Boolean(nMask & 1);
        oDesc.configurable = Boolean(nMask & 2);
        Object.defineProperty(oObj, sKey, oDesc);
        return oObj;
      };
    })();
    
    // on crée un objet vide
    var monObjet = {};
    
    // on ajoute un descripteur de données en écriture - non configurable, non énumérable
    Object.setProperty(4, monObjet, "monNombre", 25);
    
    // on ajoute un descripteur de données en lecture seule - non configurable, énumérable
    Object.setProperty(1, monObjet, "maChaîne", "Hello world!");
    
    // etc. etc. 
    
    Note : La méthode Object.setProperty() pourrait faire partie de futures méthodes natives (voir le bug ECMAScript 335).

    Syntaxe

    Object.setProperty(bitmask, obj, prop[, value/getter[, setter]])

    Paramètres

    bitmask
    Le descripteur du masque binaire (bitmask), défini ci-après.
    obj
    Le nom de l'objet dont on souhaite définir la propriété.
    prop
    Le nom de la propriété à définir ou à modifier.
    value/getter
    Paramètre optionnel. La valeur à affecter au descripteur de données ou l'accesseur à affecter au descripteur d'accesseur (selon le bitmask choisi).
    setter
    Paramètre optionnel. Le mutateur à affecter au descripteur de données. Si le marqueur situé en 0x8 est réglé pour un descripteur de données, cet argument sera ignoré.

    Description

    La méthode, non-native, Object.setProperty() fonctionne comme la méthode Object.defineProperty() mais utilise un descripteur via un masque binaire plutôt qu'un descripteur d'objet. L'argument bitmask a la structure suivante :

    flag 0x1
    La propriété est énumérable.
    flag 0x2
    La propriété est configurable.
    flag 0x4
    La propriété est accessible en écriture.
    flag 0x8
    La propriété est un descripteur d'accesseur.

    Le descripteur en masque binaire peut donc prendre les valeurs numériques suivantes :

    • 0 : Le masque binaire représente un descripteur de données en lecture seule - non configurable, non énumérable (0000).
    • 1 : Le masque binaire représente un descripteur de données en lecture seule - non configurable, énumérable (0001).
    • 2 : Le masque binaire représente un descripteur de données en lecture seule - configurable, non énumérable (0010).
    • 3 : Le masque binaire représente un descripteur de données en lecture seule - configurable, énumérable (0011).
    • 4 : Le masque binaire représente un descripteur de données en écriture - non configurable, non énumérable (0100).
    • 5 : Le masque binaire représente un descripteur de données en écriture - non configurable, énumérable (0101).
    • 6 : Le masque binaire représente un descripteur de données en écriture - configurable, non énumérable (0110).
    • 7 : Le masque binaire représente un descripteur de données en écriture - configurable, énumérable (0111).
    • 8 : Le masque binaire représente un descripteur d'accesseur - non configurable, non énumérable (1000).
    • 9 : Le masque binaire représente un descripteur d'accesseur - non configurable, énumérable (1001).
    • 10 : Le masque binaire représente un descripteur d'accesseur - configurable, non énumérable (1010).
    • 11 : Le masque binaire représente un descripteur d'accesseur - configurable, énumérable (1011).
    Note : Si le flag 0x8 est utilisé pour un descripteur d'accesseur, le flag 0x4 (writable) sera ignoré. Sinon, l'argument setter sera ignoré.

    Implémentation de HTMLSelectElement.selectedIndex

    La méthode Object.defineProperty() fonctionne également avec les objets natifs. L'exemple qui suit illustre comment implémenter la propriété selectedIndex de HTMLSelectElement dans les boutons radio.

    <!doctype html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Exemple de selectedIndex pour les groupes de boutons radio</title>
    <script type="text/javascript">
    Object.defineProperty(NodeList.prototype, "selectedIndex", {
      get: function() {
        var nIndex = this.length - 1;
        while (nIndex > -1 && !this[nIndex].checked) {
          nIndex--;
        }
        return nIndex;
      },
      
      set: function(nNewIndex) {
        if (isNaN(nNewIndex)) {
          return;
        }
        var nOldIndex = this.selectedIndex;
        if (nOldIndex > -1) {
          this[nOldIndex].checked = false;
        }
        if (nNewIndex > -1) {
          this[nNewIndex].checked = true;
        }
      },
      
      enumerable: true,
      configurable: false
    });
    
    // on essaie!
    function checkForm() {
      var nSelectedIndex = document.myForm.myRadioGroup.selectedIndex;
      if (nSelectedIndex < 0) {
        alert("Choisir un élément !!");
        return false;
      }
      alert("Félicitations !! Vous avez choisi le " + document.myForm.myRadioGroup[nSelectedIndex].value + ".");
      return true;
    }
    </script>
    </head>
    
    <body>          
      <form name="myForm" onsubmit="return(checkForm());">
        <fieldset><legend>Choisir un élément</legend>
          <p><input type="radio" name="myRadioGroup" id="ourShirt" value="chemise" /> <label for="ourShirt">chemise</label><br />
          <input type="radio" name="myRadioGroup" id="ourPants" value="pantalon" /> <label for="ourPants">pantalon</label><br />
          <input type="radio" name="myRadioGroup" id="ourBelt" value="ceinture" /> <label for="ourBelt">ceinture</label><br />
          <input type="radio" name="myRadioGroup" id="ourShoes" value="chaussures" /> <label for="ourShoes">chaussures</label></p>
          <p><span style="cursor:pointer;text-decoration:underline;color:#0000ff;" onclick="document.myForm.myRadioGroup.selectedIndex=2;">Choisissez ce que vous préférez</span></p>
          <p><input type="submit" value="Commander !" />
        </fieldset>
      </form>
    </body>
    </html>
    

    Étiquettes et contributeurs liés au document

    Étiquettes : 
    Contributors to this page: riplay777, teoli, SphinxKnight
    Dernière mise à jour par : teoli,