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
inetdelete - 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"); Identique à l'utilisation de l'opérateur in :
let answer = "name" in person; | 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"); Identique à l'utilisation de l'opérateur delete :
delete person.name; | 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");
Identique à :
let age = user.age; | 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");
Identique à :
user.age = 41; | 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"]);
Identique à l'utilisation de greet.apply() :
let msg = greet.apply(person, ["Hello"]); | 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"]); Identique au mot-clé new :
// Créer un nouveau tableau
const colors = new Array(["red", "green", "blue"]); | 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
});
Identique à l'utilisation de Object.defineProperty() :
// Ajouter une propriété
Object.defineProperty(user, "id", {
value: 123,
writable: false
}); | 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()renvoietrueoufalse
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); Presque identique à l'utilisation de Object.keys() :
let keys = Object.keys(obj); | 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);
}
});
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 :
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