Descripteurs de propriétés JavaScript
Apprenez comment les attributs de propriétés JavaScript (writable, enumerable, configurable) et les descripteurs fonctionnent, notamment defineProperty, getOwnPropertyDescriptors, freeze, seal et le mode strict.
Les attributs et descripteurs de propriétés JavaScript offrent un contrôle précis sur les propriétés des objets, permettant de développer des applications robustes et sécurisées. Cet article explore ces fonctionnalités en détail, en fournissant des aperçus pratiques et des exemples de code pour vous aider à gérer efficacement le comportement des propriétés.
Comprendre les attributs de propriétés JavaScript
Les objets JavaScript sont des collections de propriétés, et chaque propriété possède des attributs associés qui définissent son comportement. Ces attributs, souvent appelés attributs de propriétés, comprennent :
- Writable : Détermine si la valeur de la propriété peut être modifiée.
- Enumerable : Contrôle si la propriété est visible lors de l'énumération, par exemple dans une boucle
for...in. - Configurable : Spécifie si la propriété peut être supprimée ou modifiée.
Ces attributs sont essentiels pour contrôler l'accès aux propriétés des objets, garantir l'intégrité des données et implémenter l'encapsulation dans les applications JavaScript.
Plonger dans les descripteurs de propriétés
Les descripteurs de propriétés fournissent des informations détaillées sur la propriété d'un objet, en encapsulant sa valeur et ses attributs. Ils sont récupérés avec Object.getOwnPropertyDescriptor(obj, propName) et définis avec Object.defineProperty(obj, propName, descriptor). Un object descripteur de propriété peut contenir :
value: La valeur associée à la propriété.writable: Indique si la valeur de la propriété peut être modifiée.enumerable: Indique si la propriété est énumérable.configurable: Détermine si le descripteur de propriété peut être modifié et si la propriété peut être supprimée de l'objet.
Remarque : Lorsque vous créez une propriété de façon normale (user.name = "John"), les trois attributs sont définis à true. Mais lors de la définition d'une nouvelle propriété via Object.defineProperty, tout attribut non spécifié prend la valeur false par défaut.
Object.getOwnPropertyDescriptor examine uniquement les propriétés propres de l'objet. Si vous demandez une propriété que l'objet hérite de son prototype (ou une propriété qui n'existe pas du tout), il retourne undefined.
Pour en savoir plus sur la façon dont les objets héritent des propriétés, consultez Héritage par prototype.
Descripteurs de données vs descripteurs d'accesseurs
Jusqu'ici, nous avons décrit les descripteurs de données, qui stockent une value avec l'attribut writable. JavaScript prend également en charge les descripteurs d'accesseurs, qui remplacent value/writable par des fonctions getter et setter :
get: une fonction appelée lors de la lecture de la propriété (ne prend aucun argument).set: une fonction appelée lors de l'affectation à la propriété (reçoit la nouvelle valeur).
Un descripteur est soit un descripteur de données, soit un descripteur d'accesseur — jamais les deux. Combiner value/writable avec get/set provoque une erreur. Les deux types partagent toujours les attributs enumerable et configurable.
Les propriétés accesseurs permettent de calculer une valeur lors de la lecture ou de la valider lors de l'écriture. Ici, nous exposons un accesseur fullName appuyé sur deux propriétés de données :
Pour un traitement plus approfondi de la syntaxe get/set (y compris la notation abrégée dans les littéraux d'objet), consultez Getters et setters de propriétés. Puisque les getters et setters s'exécutent avec this lié à l'objet, il est également utile de comprendre Les méthodes d'objets et "this".
Définir et lire plusieurs propriétés à la fois
Pour travailler avec plusieurs propriétés en une seule étape, JavaScript fournit les équivalents pluriels des méthodes ci-dessus :
Object.defineProperties(obj, descriptors)définit plusieurs propriétés à partir d'une carte de descripteurs.Object.getOwnPropertyDescriptors(obj)retourne les descripteurs de toutes les propriétés propres (y compris les propriétés non-énumérables et les clés de symbole) sous forme d'un seul objet.
Object.getOwnPropertyDescriptors est particulièrement utile pour cloner un objet avec ses attributs — un simple spread ou Object.assign copie les valeurs mais réinitialise chaque attribut à true et ignore les accesseurs.
Manipuler les attributs de propriétés
Comprendre et manipuler les attributs de propriétés est essentiel pour un développement JavaScript efficace. Explorons comment contrôler ces attributs pour affiner le comportement des propriétés.
Rendre une propriété non-modifiable
Empêcher les modifications d'une propriété garantit la cohérence des données. Cela peut être réalisé en définissant l'attribut writable à false.
Le comportement d'une affectation échouée dépend du mode d'exécution du code. En mode non-strict, écrire dans une propriété non-modifiable échoue silencieusement : l'affectation est simplement ignorée, aucune erreur n'est levée et l'exécution continue — ce qui peut masquer des bugs. En mode strict ("use strict", et par défaut dans les modules ES et les corps de classe), la même affectation lève une TypeError. Cette règle s'applique à toute opération qui viole un attribut : supprimer une propriété non-configurable ou ajouter une propriété à un objet non-extensible échoue également silencieusement en mode non-strict et lève une exception en mode strict.
Masquer une propriété de l'énumération
Il est parfois nécessaire de masquer des propriétés lors des processus d'énumération, comme les boucles for...in. Pour cela, il suffit de définir l'attribut enumerable à false.
Empêcher la suppression et la modification d'une propriété
Pour garantir qu'une propriété reste une partie permanente d'un objet, définissez l'attribut configurable à false.
Marquer une propriété comme non-configurable est une opération irréversible — il n'existe aucun attribut pour la rendre à nouveau configurable, et vous ne pouvez plus basculer enumerable ni convertir la propriété d'un descripteur de données en descripteur d'accesseur.
Il existe cependant deux exceptions importantes lorsqu'une propriété est non-configurable :
- Vous pouvez changer
writabledetrueàfalse(mais pas defalseàtrue). - Si la propriété est toujours
writable: true, vous pouvez changer savalue— soit par affectation directe, soit viaObject.defineProperty.
En d'autres termes, configurable: false verrouille la structure de la propriété, mais pas nécessairement sa valeur. Pour vraiment figer la valeur d'une propriété, définissez à la fois configurable: false et writable: false.
API de haut niveau basées sur ces attributs
Il est rarement nécessaire de définir les attributs propriété par propriété. JavaScript intègre trois méthodes qui modifient ces attributs sur l'ensemble d'un objet :
Object.preventExtensions(obj)— empêche l'ajout de nouvelles propriétés. Les propriétés existantes peuvent encore être modifiées ou supprimées.Object.seal(obj)— empêche l'ajout et la suppression de propriétés en marquant chaque propriété existanteconfigurable: false. Les valeurs peuvent encore être modifiées.Object.freeze(obj)— la plus stricte : scelle l'objet et rend chaque propriétéwritable: false, de sorte que rien ne peut être ajouté, supprimé ou modifié.
Chaque méthode dispose d'une vérification correspondante : Object.isExtensible, Object.isSealed et Object.isFrozen. Notez que ces opérations ne s'appliquent qu'à un niveau de profondeur — Object.freeze ne gèle pas les objets imbriqués (il s'agit d'un gel « superficiel »).
Conclusion
Les attributs et descripteurs de propriétés vous donnent un contrôle précis sur le comportement des propriétés d'un objet :
- Un descripteur de données associe une
valueàwritable; un descripteur d'accesseur utilise à la place des fonctionsget/set. Les deux partagentenumerableetconfigurable. - Lisez les attributs avec
Object.getOwnPropertyDescriptor(une propriété) ouObject.getOwnPropertyDescriptors(toutes les propriétés propres) ; définissez-les avecObject.definePropertyouObject.defineProperties. Les propriétés héritées et manquantes retournentundefined. configurable: falseest irréversible et verrouille la structure de la propriété, bien qu'une propriété encorewritablepuisse voir sa valeur modifiée et son attributwritabledésactivé.- Violer un attribut échoue silencieusement en mode non-strict mais lève une
TypeErroren mode strict. - Utilisez
Object.freeze,Object.sealetObject.preventExtensionslorsque vous souhaitez verrouiller un objet entier plutôt que des attributs individuels.
Prochaines étapes : plongez dans Getters et setters de propriétés pour la syntaxe des accesseurs, Les méthodes d'objets et "this" pour le comportement de this à l'intérieur de ceux-ci, et Héritage par prototype pour voir comment la recherche de propriétés parcourt la chaîne de prototypes.