JavaScript Reflect

L'objet Reflect

Reflect est un objet avec des méthodes pour des opérations de bas niveau sur les objets JavaScript.

Avec l' objet Reflect , vous pouvez obtenir, définir, supprimer et vérifier les propriétés des objets de manière cohérente.

Reflect a été ajouté à JavaScript dans ES6 (2015).

Votre boîte à outils

Reflect est une boîte à outils pour travailler avec des objets de manière sûre et cohérente.


Avant Reflect

Avant Reflect, les opérations sur les objets étaient éparpillées :

  • Utilisation d'opérateurs comme in et delete
  • Utilisation de méthodes comme Object.defineProperty
  • Utilisation de mécanismes de langage comme [[ Get ]] et [[ Set ]]

Après Reflect

Reflect regroupe toutes les opérations sur les objets dans des méthodes claires :

  • Les méthodes Reflect unifient les opérations sur les objets
  • Les méthodes Reflect sont plus prévisibles que les opérateurs (in/delete)
  • Les méthodes Reflect fournissent des valeurs de retour standard au lieu d'erreurs
  • Les méthodes Reflect sont plus propres et plus sûres pour la méta-programmation
  • Les méthodes Reflect sont adaptées à l'objet Proxy

Exemples

Avec Reflect.has() , vous obtenez l'opérateur in sous forme de fonction.

Avec Reflect.delete() , vous obtenez l'opérateur delete sous forme de fonction.

Pourquoi Reflect

Reflect est sûr et flexible, surtout lorsqu'il est utilisé à l'intérieur d'un Proxy.


Reflect.has()

La méthode Reflect.has() vérifie si un objet a une propriété spécifique.

La méthode Reflect.has() est similaire à l'opérateur in .

Vérifier si la propriété existe

// Créer un objet
const person = {name: "John", lastname: "Doe"};

let answer = Reflect.has(person, "name");
Essayez-le vous-même »

Identique à l'utilisation de l'opérateur in :

let answer = "name" in person;
Essayez-le vous-même »
Syntaxe
Reflect.has(obj, prop)
Propriétés
obj - l'objet cible
prop - la propriété à vérifier
Renvoie
true - si vrai
false si faux
Exceptions
TypeError levé si obj n'est pas un objet

Reflect.deleteProperty()

La méthode Reflect.deleteProperty() supprime une propriété d'un objet.

La méthode Reflect.deleteProperty() est similaire à l'opérateur delete .

Supprimer une propriété

// Créer un objet
const person = {name: "John", lastname: "Doe"};

Reflect.deleteProperty(person, "name");
Essayez-le vous-même »

Identique à l'utilisation de l'opérateur delete :

delete person.name;
Essayez-le vous-même »
Syntaxe
Reflect.deleteProperty(obj, prop)
Propriétés
obj - l'objet cible
prop - la propriété à supprimer
Renvoie
true - si vrai
false si faux
Exceptions
TypeError levé si obj n'est pas un objet

Reflect.get()

La méthode Reflect.get() récupère la valeur d'une propriété :

Exemple

// Créer un objet
const user = {name: "Jan", age: 40};

let age = Reflect.get(user, "age");
Essayez-le vous-même »

Identique à :

let age = user.age;
Essayez-le vous-même »
Syntaxe
Reflect.get(obj, prop [,receiver])
Propriétés
obj - l'objet cible
prop - la propriété à obtenir
receiver - la valeur de this si c'est un getter
Renvoie
La valeur de la propriété
Exceptions
TypeError levé si obj n'est pas un objet

Reflect.set()

La méthode Reflect.set() définit la valeur d'une propriété :

Exemple

// Créer un objet
const user = {name: "Jan", age: 40};

Reflect.set(user, "age", 41);

let age = Reflect.get(user, "age");
Essayez-le vous-même »

Identique à :

user.age = 41;
Essayez-le vous-même »
Syntaxe
Reflect.set(obj, prop, value [,receiver])
Propriétés
obj - l'objet cible
prop - la propriété à définir
value - la valeur à définir
receiver - la valeur de this si c'est un setter
Renvoie
true - pour succès
false - si non
Exceptions
TypeError levé si obj n'est pas un objet

Reflect.apply()

La méthode Reflect.apply() appelle une fonction avec une valeur this et un tableau d'arguments.

Exemple

function greet(message) {
return message + ", " + this.name;
}

const person = {name: "Jan"};

let msg = Reflect.apply(greet, person, ["Hello"]);
Essayez-le vous-même »

Identique à l'utilisation de greet.apply() :

let msg = greet.apply(person, ["Hello"]);
Essayez-le vous-même »
Syntaxe
Reflect.apply(function, this, arguments)
Propriétés
function - objet cible (fonction)
this - la valeur de this appelant la cible
arguments - objet semblable à un tableau des arguments de la fonction
Renvoie
La valeur de retour de la fonction
Exceptions
TypeError levé si function n'est pas une fonction ou arguments n'est pas un objet

Remarque

Reflect.apply() est préféré lorsque :

  • Vous faites de la méta-programmation
  • Vous êtes à l'intérieur d'un gestionnaire Proxy
  • Vous voulez des comportements cohérents (pas d'erreurs silencieuses)
  • Vous voulez refléter les opérations internes de JavaScript

Reflect.construct()

La méthode Reflect.construct() agit comme l'opérateur new, créant une nouvelle instance de la cible avec les arguments fournis. newTarget permet des valeurs new.target personnalisées pour l'héritage.

Exemple

// Créer un nouveau tableau
const colors = Reflect.construct(Array, ["red", "green", "blue"]);
Essayez-le vous-même »

Identique au mot-clé new :

// Créer un nouveau tableau
const colors = new Array(["red", "green", "blue"]);
Essayez-le vous-même »
Syntaxe
Reflect.construct(obj, args [, newTarget])
Propriétés
obj - l'objet constructeur
args - un objet semblable à un tableau des arguments à passer
newTarget - le constructeur
Renvoie
Un nouvel objet construit à partir de la liste des arguments
Exceptions
TypeError levé si obj ou newTarget n'est pas un constructeur, ou si args n'est pas un objet

Reflect.defineProperty()

La méthode Reflect.defineProperty() définit ou modifie une propriété.

Exemple

// Créer un objet
const user = {};

// Ajouter une propriété
Reflect.defineProperty(user, "id", {
value: 123,
writable: false
});
Essayez-le vous-même »

Identique à l'utilisation de Object.defineProperty() :

// Ajouter une propriété
Object.defineProperty(user, "id", {
value: 123,
writable: false
});
Essayez-le vous-même »
Syntaxe
Reflect.defineProperty(obj, prop, attributes)
Propriétés
obj - l'objet cible
prop - la propriété à définir
attributes - un objet semblable à un tableau des attributs de la propriété
Renvoie
Exceptions
TypeError levé si obj n'est pas un objet ou attributes n'est pas un objet

Reflect.defineProperty() dans Proxy

Reflect.defineProperty() doit être utilisé dans Proxy

S'il est utilisé dans un Proxy, le piège defineProperty doit renvoyer true ou false .

  • Object.defineProperty() renvoie l'objet cible
  • Reflect.defineProperty() renvoie true ou false

Reflect.ownKeys()

La méthode Reflect.ownKeys(obj) renvoie un tableau des clés de propriété propres d'un objet (basées sur des chaînes et des symboles), similaire à la combinaison de Object.getOwnPropertyNames() et Object.getOwnPropertySymbols().

Exemple

const sym = Symbol("secret");
const obj = { a: 1, [sym]: 2 };

let keys = Reflect.ownKeys(obj);
Essayez-le vous-même »

Presque identique à l'utilisation de Object.keys() :

let keys = Object.keys(obj);
Essayez-le vous-même »
Syntaxe
Reflect.ownKeys(obj)
Propriétés
obj - l'objet cible
Renvoie
Un tableau des clés de propriété propres de l'objet, y compris des chaînes et des symboles
Exceptions
TypeError levé si obj n'est pas un objet

Pourquoi utiliser Reflect ?

Reflect.ownKeys() renvoie également des symboles.

Object.keys() ne le fait pas.


Reflect.isExtensible()

La méthode Reflect.isExtensible() vérifie si un objet est extensible (peut avoir des propriétés ajoutées), similaire à Object.isExtensible().

Exemple

let answer = Reflect.isExtensible(obj);

Identique à l'utilisation de Object.isExtensible() :

let answer = Object.isExtensible(obj);
Syntaxe
Reflect.isExtensible(obj)
Propriétés
obj - l'objet cible
Renvoie
true - est extensible
false - n'est pas extensible
Exceptions
TypeError levé si obj n'est pas un objet

Pourquoi utiliser Reflect ?

Object.isExtensible() est une méthode utilisateur - pas partie de la machinerie interne des pièges.

Reflect.isExtensible() se mappe directement à la méthode interne [[IsExtensible]].

Reflect.isExtensible() gère correctement les cibles primitives, ce qui est important lorsqu'elles sont proxyées.

Reflect.isExtensible(1); // TypeError
Object.isExtensible(1); // false (ne lève pas d'erreur)

Quand utiliser Reflect ?

Cas Utiliser Pourquoi
Obtenir / définir des valeurs Oui Si vous avez besoin de valeurs de retour cohérentes
Créer de nouveaux objets Oui Reflect.construct() fonctionne avec Proxy
Appeler une fonction avec un contexte Oui Reflect.apply() est plus propre que func.apply()
Méta programmation Oui Conçu pour des tâches de bas niveau
Travail simple sur les objets Non Utilisez la syntaxe JS normale

Reflect avec Proxy (très courant)

Proxy vous permet d'intercepter des opérations sur des objets :

Exemple

// Créer un objet
const user = { name: "Jan", age: 40 };

// Créer un Proxy
const proxy = new Proxy(user, {
set(target, property, value) {
log(property + ": " + value);
// transfert sûr
return Reflect.set(target, property, value);
}
});
Essayez-le vous-même »

Remarque

Reflect peut fournir des appels de transfert sûrs et unifiés.

Reflect garantit qu'un Proxy se comporte comme un objet normal.


Proxy et Reflect

Proxy a été conçu en premier. Reflect a été conçu en second.

Proxy a été conçu pour permettre aux développeurs JavaScript de :

  • Intercepter l'accès aux propriétés
  • Remplacer les comportements par défaut des propriétés
  • Valider les données
  • Envelopper des fonctions
  • Virtualiser des objets
  • Créer des objets réactifs

L'idée de Proxy a été développée pendant la phase de conception de ES6 (2015) avant que Reflect n'existe.

Cependant, Proxy avait un gros problème :

"Comment transférer des opérations interceptées en toute sécurité ?"

JavaScript n'avait pas d'équivalents fonctionnels pour de nombreuses opérations.

En raison de cette limitation, Reflect a été inventé.


Histoire de JavaScript Reflect

Reflect a été introduit parce que Proxy en avait besoin.

Avant Reflect :

  • delete, in, new étaient des opérateurs
  • certaines opérations levaient des erreurs
  • les opérations sur les objets renvoyaient des valeurs incohérentes
  • aucune version générique de l'accès aux propriétés n'existait
  • aucune façon de transférer des appels de constructeur n'existait

Cela rendait impossible l'implémentation sûre de Proxy.

Ainsi, ES6 (2015) a introduit Reflect pour :

  • fournir des versions propres, basées sur des fonctions de chaque opération interne
  • renvoyer des booléens prévisibles au lieu d'objets
  • éviter des erreurs inutiles
  • refléter le comportement du moteur JavaScript
  • donner aux pièges Proxy un chemin de transfert fiable