Maybaygiare.org

Blog Network

Attributs des propriétés d’objet dans JavaScript

Dans cet article de blog, nous examinons de plus près comment la spécification ECMAScript voit les objets JavaScript. En particulier, les propriétés ne sont pas atomiques dans la spécification, mais composées de plusieurs attributs (pensez aux champs d’un enregistrement). Même la valeur d’une propriété de données est stockée dans un attribut !

Table des matières :

La structure des objets #

Dans la spécification ECMAScript, un objet se compose de:

  • Emplacements internes, qui sont des emplacements de stockage qui ne sont pas accessibles à partir de JavaScript, uniquement aux opérations de la spécification.
  • Une collection de propriétés. Chaque propriété associe une clé à des attributs (pensez aux champs d’un enregistrement).

Emplacements internes #

Voici comment la spécification décrit les emplacements internes (l’accent est le mien):

  • Les emplacements internes correspondent à l’état interne associé aux objets et utilisé par divers algorithmes de spécification ECMAScript.
  • Les emplacements internes ne sont pas des propriétés d’objet et ils ne sont pas hérités.
  • Selon la spécification d’emplacement interne spécifique, cet état peut être constitué de valeurs :
    • de n’importe quel type de langage ECMAScript ou
    • de valeurs de type de spécification ECMAScript spécifiques.
  • Sauf indication contraire explicite, les emplacements internes sont alloués dans le cadre du processus de création d’un objet et ne peuvent pas être ajoutés dynamiquement à un objet.
  • Sauf indication contraire, la valeur initiale d’un emplacement interne est la valeur undefined.
  • Divers algorithmes dans cette spécification créent des objets qui ont des emplacements internes. Cependant, le langage ECMAScript ne fournit aucun moyen direct d’associer des emplacements internes à un objet.
  • Les méthodes internes et les emplacements internes sont identifiés dans cette spécification à l’aide de noms placés entre crochets doubles ].

Il existe deux types d’emplacements internes :

  • Emplacements de méthode pour manipuler des objets (obtenir des propriétés, définir des propriétés, etc.)
  • Data slots with storage (listed in the table below)
Internal data slot Type
] null | object
] boolean
] List of entries

Descriptions for these data slots :

Clés de propriété #

La clé d’une propriété est soit :

  • Une chaîne
  • Un symbole

Attributs de propriété #

Il existe deux types de propriétés et elles ont des attributs différents :

  • Une propriété de données stocke des données. Ses attributs value contiennent n’importe quelle valeur JavaScript.
  • Une propriété accesseur a une fonction getter et/ou une fonction setter. Le premier est stocké dans l’attribut get, le second dans l’attribut set.

Le tableau suivant répertorie tous les attributs de propriété.

Kind of property Name and type of attribute Default value
Data property value: any undefined
writable: boolean false
Accessor property get(): any undefined
set(v: any): void undefined
All properties configurable: boolean false
enumerable: boolean false

We have already encountered the attributes valueget, and set. The other attributes work as follows:

  • writable détermine si la valeur d’une propriété de données peut être modifiée.
  • configurable détermine si les attributs d’une propriété peuvent être modifiés. S’il s’agit de false, alors :

    • Vous ne pouvez pas supprimer la propriété.
    • Vous ne pouvez pas changer une propriété d’une propriété de données en une propriété d’accesseur ou vice versa.
    • Vous ne pouvez modifier aucun attribut autre que value.
    • Cependant, un changement d’attribut supplémentaire est autorisé: Vous pouvez changer writable de true en false. La justification de cette anomalie est historique : La propriété .length des tableaux a toujours été inscriptible et non configurable. Permettre à son attribut writable d’être modifié nous permet de geler les tableaux.
  • enumerable influence certaines opérations (telles que Object.assign()). S’il s’agit de false, ces opérations ignorent la propriété.

Descripteurs de propriété #

Un descripteur de propriété code les attributs d’une propriété en tant qu’objet JavaScript. Leurs interfaces TypeScript se présentent comme suit.

Les points d’interrogation indiquent que chaque propriété est facultative. Si vous omettez une propriété lors du passage d’un descripteur à une opération, sa valeur par défaut est utilisée.

Récupération des descripteurs pour les propriétés #

Le code suivant récupère le descripteur d’objet pour la propriété de données first:

Dans l’exemple suivant, nous récupérons le descripteur de propriété pour le getter fullName:

L’utilisation de desc() à la ligne A est une solution de contournement pour que .deepEqual() fonctionne.

Création de nouvelles propriétés via des descripteurs #

Vous pouvez également créer de nouvelles propriétés via des descripteurs de propriétés :

Modifier des propriétés existantes via des descripteurs #

Si une propriété propre existe déjà, la définir via un descripteur modifie cette propriété. D’une part cela nous permet d’utiliser Object.defineProperty() comme affectation:

D’un autre côté, nous pouvons également utiliser Object.defineProperty() pour transformer une propriété de données en getter (et vice versa) :

Piège: les propriétés en lecture seule héritées ne peuvent pas être affectées à #

Si une propriété héritée est en lecture seule, nous ne pouvons pas utiliser l’affectation pour la modifier. La justification est que l’annulation d’une propriété héritée en créant une propriété propre peut être considérée comme une modification non destructive de la propriété héritée. On peut dire que si une propriété n’est pas accessible en écriture, nous ne devrions pas pouvoir le faire.

Regardons un exemple:

Nous ne pouvons pas modifier la propriété via l’affectation. Mais nous pouvons toujours créer une propriété propre en la définissant :

Object.defineProperty(obj, 'prop', {value: 2});assert.equal(obj.prop, 2);

Les propriétés de l’accesseur qui n’ont pas de setter sont également considérées comme en lecture seule :

API: descripteurs de propriétés #

Les fonctions suivantes vous permettent de travailler avec des descripteurs de propriétés :

Cas d’utilisation de l’objet.getOwnPropertyDescriptors() #

Objet.getOwnPropertyDescriptors(): copie des propriétés dans un objet #

Depuis ES6, JavaScript a déjà une méthode d’outil pour copier les propriétés : Object.assign(). Cependant, cette méthode utilise de simples opérations get et set pour copier une propriété dont la clé est key :

target = source;

Cela signifie qu’elle ne crée une copie fidèle d’une propriété que si :

  • Son attribut writable est true et son attribut enumerable est true (car c’est ainsi que l’affectation crée des propriétés).
  • C’est une propriété de données.

L’exemple suivant illustre cette limitation. L’objet source a un setter dont la clé est data.

Si nous utilisons Object.assign() pour copier la propriété data, alors la propriété d’accesseur data est convertie en une propriété de données :

Heureusement, en utilisant Object.getOwnPropertyDescriptors() avec Object.defineProperties() copie fidèlement la propriété data:

Piège: méthodes de copie utilisant super#

Une méthode utilisant super est fermement connectée à son objet d’origine (l’objet dans lequel elle est stockée). Il n’existe actuellement aucun moyen de copier ou de déplacer une telle méthode vers un objet différent.

Objet.getOwnPropertyDescriptors(): clonage d’objets #

Le clonage superficiel est similaire à la copie de propriétés, c’est pourquoi Object.getOwnPropertyDescriptors() est également un bon choix ici.

Pour créer le clone, nous utilisons Object.create():

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.