Cette page a été traduite à partir de l'anglais par la communauté.Vous pouvez contribuer en rejoignant la communauté francophone sur MDN Web Docs.
Object.defineProperty()
Baseline Widely available
Cette fonctionnalité est bien établie et fonctionne sur de nombreux appareils et versions de navigateurs. Elle est disponible sur tous les navigateurs depuis juillet 2015.
La méthode statiqueObject.defineProperty() permet de définir une nouvelle propriété ou de modifier une propriété existante, directement sur un objet. La méthode renvoie l'objet modifié.
Note :Cette méthode est directement appelée via le constructeurObject plutôt que sur les instances de typeObject.
Dans cet article
Exemple interactif
const object1 = {};Object.defineProperty(object1, "property1", { value: 42, writable: false,});object1.property1 = 77;// Throws an error in strict modeconsole.log(object1.property1);// Expected output: 42Syntaxe
Object.defineProperty(obj, prop, descripteur);Paramètres
objL'objet sur lequel on souhaite définir ou modifier une propriété.
propLe nom ou le symbole (
Symbol) de la propriété qu'on définit ou qu'on modifie.descripteurLe descripteur de la propriété qu'on définit ou qu'on modifie.
Valeur de retour
L'objet qui a été passé à la fonction et qui a éventuellement été modifié.
Description
Cette méthode permet d'ajouter ou de modifier une propriété d'un objet avec une certaine précision. En effet, quand on ajoute une propriété « normalement » (via une affectation), on crée une propriété dont le comportement par défaut fait qu'elle sera listée dans une énumération de propriétés (par exemple avec une bouclefor...in ou via la méthodeObject.keys), dont la valeur peut être changée et qui peut être supprimée viadelete. La méthodeObject.defineProperty() permet de préciser le comportement attendu, potentiellement différent de celui par défaut.
Les descripteurs de propriété existent en deux versions : les descripteurs de données et les descripteurs d'accesseur. Un descripteur de données est une propriété qui possède une valeur et qui peut ou non être accessible en écriture. Un descripteur d'accesseur est une propriété décrite par une paire d'accesseur/mutateur (getter/setter) qui sont des fonctions. Un descripteur est un descripteur de données ou un descripteur d'accesseur, il ne peut pas être les deux.
Les descripteurs de données et d'accesseur sont des objets. Ils partagent les propriétés suivantes (la valeur par défaut indiquée est utilisée lorsqu'on passe parObject.defineProperty()) :
configurabletruesi et seulement si le type de ce descripteur de propriété peut être changé et si la propriété peut/pourra être supprimée de l'objet correspondant..La valeur par défaut estfalse.enumerabletruesi et seulement si la propriété apparaît lors de l'énumération des propriétés de l'objet correspondant.La valeur par défaut estfalse.
Un descripteur de données possède les propriétés optionnelles suivantes :
valueLa valeur associée à la propriété. Peut être n'importe quelle valeur JavaScript valide (un nombre, un objet, etc.).La valeur par défaut est
undefined.writabletruesi et seulement si la valeur associée à la propriété peut être modifiée en utilisant unopérateur d'affectation.La valeur par défaut estfalse.
Un descripteur d'accesseur possède les propriétés optionnelles suivantes :
getUne fonction qui est utilisée comme accesseur (getter) pour la propriété ou bien
undefineds'il n'existe pas d'accesseur. La valeur de retour de la fonction sera utilisée comme valeur pour la propriété. Lorsqu'on accède à la propriété, la fonction est appelée sans argument avecthisqui est l'objet pour lequel on souhaite consulter la propriété.La valeur par défaut estundefined.setUne fonction qui est utilisée comme mutateur (setter) pour la propriété ou bien
undefineds'il n'existe pas de mutateur. Pour unique argument, la fonction recevra la nouvelle valeur à affecter à la propriété. Le contextethispassé est l'objet sur lequel on souhaite modifier la propriété.La valeur par défaut estundefined.
Si un descripteur ne possède aucune des clésvalue,writable,get ouset, il est considéré comme un descripteur de données. Si un descripteur possède à la fois une propriétévalue ouwritable et une propriétéget ouset, un exception sera déclenchée.
Il faut garder à l'esprit que ces options ne sont pas nécessairement les descripteurs des propriétés propres. Elles peuvent être héritées et faire partie de la chaine des prototypes. Afin de s'assurer que les valeur par défaut sont préservées, on peut d'abord geler le prototypeObject.prototype, définir toutes les options explicitement ou faire pointer la propriétéObject.prototype.__proto__ versnull (par exemple avecObject.create(null)).
var obj = {};// en utilisant __proto__Object.defineProperty(obj, "clé", { __proto__: null, // aucune propriété héritée value: "static", // non énumérable // non configurable // non accessible en écriture // par défaut});// en étant expliciteObject.defineProperty(obj, "clé", { enumerable: false, configurable: false, writable: false, value: "static",});// en recyclant un objetfunction avecValeur(valeur) { var d = avecValeur.d || (avecValeur.d = { enumerable: false, writable: false, configurable: false, value: null, }); if (d.value !== valeur) { d.value = valeur; } return d;}// ... autres instructions... puisObject.defineProperty(obj, "clé", avecValeur("static"));// si la méthode freeze est disponible,// on peut empêcher que du code ajoute des// propriétés (valeur, get, set, enumerable,// writable, configurable) au prototype d'Object(Object.freeze || Object)(Object.prototype);Exemples
Pour plus d'exemples utilisant la méthodeObject.defineProperty avec une syntaxe de masque binaire, voirles exemples supplémentaires.
Créer une propriété
Lorsqu'une propriété n'existe pas pour l'objet,Object.defineProperty() créera une nouvelle propriété telle qu'elle est décrite. Certains champs du descripteur peuvent manquer, les valeurs par défaut seront alors utilisées. Tous les booléens ontfalse pour valeur par défaut. Une propriété définie sansget/set/value/writable est appelée « générique » et « correspond » à un descripteur de données.
var o = {}; // on crée un nouvel objet// Exemple d'une propriété ajoutée via defineProperty// avec un descripteur de donnéesObject.defineProperty(o, "a", { value: 37, writable: true, enumerable: true, configurable: true,});// la propriété 'a' existe pour l'objet o et vaut 37// Exemple d'une propriété ajoutée via defineProperty// avec un descripteur d'accesseurvar valeurB = 38;Object.defineProperty(o, "b", { get: function () { return valeurB; }, set: function (nouvelleValeur) { valeurB = nouvelleValeur; }, enumerable: true, configurable: true,});o.b; // 38// la propriété 'b' existe pour l'objet o// et vaut 38// La valeur de o.b est désormais toujours// identique à valeurB, sauf si o.b est redéfini// On ne peut pas mélanger les deux :Object.defineProperty(o, "conflit", { value: 0x9f91102, get: function () { return 0xdeadbeef; },});// une exception TypeError sera lancée : value n'apparaît// que dans les descripteurs de données// get n'apparait que dans les descripteurs d'accesseurModifier une propriété existante
Quand une propriété existe d'ores et déjà pour un objet,Object.defineProperty() tentera de modifier la propriété pour qu'elle corresponde aux valeurs indiquées dans le descripteur et à la configuration de l'objet courant. Si l'ancien descripteur avaitconfigurable àfalse (la propriété est dite non-configurable), aucun attribut, à l'exception dewritable, ne peut être changé. Dans ce cas, il n'est pas possible de changer entre les types de descripteur.
Si une propriété est non-configurable, son attributwritable ne peut être mis qu'àfalse.
Une exceptionTypeError peut être levée quand on essaie de modifier des attributs de propriété non-configurables (en dehors des attributsvalue etwritable) sauf dans le cas où les valeurs souhaitées sont les mêmes que les valeurs courantes.
Attributwritable
Lorsque l'attributwritable vautfalse pour la propriété, cette dernière n'est plus accessible en écriture. Il est impossible de la réaffecter.
var o = {}; // On crée un nouvel objetObject.defineProperty(o, "a", { value: 37, writable: false });console.log(o.a); // inscrit 37 dans les journaux (logs)o.a = 25; // Aucune exception n'est lancée (on aurait une// exception en mode strict, y compris si la// valeur souhaitée avait été la même)console.log(o.a); // inscrit toujours 37.//L'affectation n'a pas fonctionné.// En mode strict(function () { "use strict"; var o = {}; Object.defineProperty(o, "b", { value: 2, writable: false, }); o.b = 3; // déclenche une TypeError: "b" est en lecture seule return o.b; // renvoie 2 sans la ligne précédente})();Comme on l'a vu dans l'exemple, essayer de modifier une propriété non accessible en écriture ne la modifie pas. Cela ne rend pas d'erreur non plus (en mode non-strict).
Attributenumerable
L'attribut de propriétéenumerable permet de définir si la propriété est sélectionnée parObject.assign() ou via l'opérateurde décomposition (spread). Pour les propriétés qui ne sont pas nommées avec des symboles, les propriétés énumérables correspondent aux propriétés qui sont listées avec une bouclefor...in ou avec la méthodeObject.keys().
var o = {};Object.defineProperty(o, "a", { value: 1, enumerable: true,});Object.defineProperty(o, "b", { value: 2, enumerable: false,});Object.defineProperty(o, "c", { value: 3,}); // enumerable vaut false par défauto.d = 4; // enumerable vaut true par défaut// lorsqu'on crée une propriété// en la définissantObject.defineProperty(o, Symbol.for("e"), { value: 5, enumerable: true,});Object.defineProperty(o, Symbol.for("f"), { value: 6, enumerable: false,});for (var i in o) { console.log(i);}// affiche 'a' et 'd' (dans un ordre indéfini)Object.keys(o); // ['a', 'd']o.propertyIsEnumerable("a"); // trueo.propertyIsEnumerable("b"); // falseo.propertyIsEnumerable("c"); // falseo.propertyIsEnumerable("d"); // trueo.propertyIsEnumerable(Symbol.for("e")); // trueo.propertyIsEnumerable(Symbol.for("f")); // falsevar p = { ...o };p.a; // 1p.b; // undefinedp.c; // undefinedp.d; // 4p[Symbol.for("e")]; // 5p[Symbol.for("f")]; // undefinedAttributconfigurable
L'attributconfigurable permet de contrôler si la propriété peut être supprimée et si les autres attributs de propriété (voir ci-avant), à l'exception devalue ou dewritable, peuvent être modifiés.
var o = {};Object.defineProperty(o, "a", { get: function () { return 1; }, configurable: false,});Object.defineProperty(o, "a", { configurable: true });// renvoie une TypeErrorObject.defineProperty(o, "a", { enumerable: true });// renvoie une TypeErrorObject.defineProperty(o, "a", { set: function () {} });// renvoie une TypeError (set était non défini avant)Object.defineProperty(o, "a", { get: function () { return 1; },});// renvoie une TypeError// (bien que le nouveau get soit identique au précédent)Object.defineProperty(o, "a", { value: 12 });// renvoie une TypeErrorconsole.log(o.a); // log 1delete o.a; // Rien ne se passeconsole.log(o.a); // log 1Si l'attributconfigurable deo.a avait ététrue, aucune de ces erreurs n'aurait été renvoyée et la propriété aurait été supprimée au final.
Ajouter des propriétés et des valeurs par défaut
Il est toujours important de savoir comment les valeurs par défaut sont appliquées. Le comportement est souvent différent entre une affectation simple et l'utilisation deObject.defineProperty(). Par exemple :
var o = {};o.a = 1;// est équivalent à :Object.defineProperty(o, "a", { value: 1, writable: true, configurable: true, enumerable: true,});// D'un autre côté,Object.defineProperty(o, "a", { value: 1 });// sera équivalent à :Object.defineProperty(o, "a", { value: 1, writable: false, configurable: false, enumerable: false,});Accesseurs et mutateurs adaptés
L'exemple ci-dessous illustre comment implémenter un objet qui archive des données. Lorsque la propriététempérature est définie, on ajoute une entrée au tableauarchive :
function Archiviste() { var température = null; var archive = []; Object.defineProperty(this, "température", { get: function () { console.log("accès !"); return température; }, set: function (value) { température = value; archive.push({ val: température }); }, }); this.getArchive = function () { return archive; };}var arc = new Archiviste();arc.température; // "accès !"arc.température = 11;arc.température = 13;arc.getArchive(); // [{val: 11}, {val: 13}]Spécifications
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-object.defineproperty> |