Movatterモバイル変換


[0]ホーム

URL:


MDN Web Docs

Cette page a été traduite à partir de l'anglais par la communauté. Vous pouvez également contribuer en rejoignant la communauté francophone sur MDN Web Docs.

Métaprogrammation

À partir d'ECMAScript 2015, JavaScript fournit les objets natifsProxy etReflect. Ces objets permettent d'intercepter et de définir des comportements spécifiques pour certaines opérations fondamentales du langage (par exemple la recherche d'une propriété, l'affectation, l'énumération, l'appel d'une fonction, etc.). Grâce à ces deux objets, il est possible d'interagir avec le langage lui-même (on parle alors de métaprogrammation).

Les proxies

Introduits avec ECMAScript 2015, les objetsProxy permettent d'intercepter certaines opérations JavaScript et de définir le comportement à avoir quand celles-ci se produisent. Par exemple, on peut intercepter l'accès à une propriété d'un objet :

js
var handler = {  get: function (cible, nom) {    return nom in cible ? cible[nom] : 42;  },};var p = new Proxy({}, handler);p.a = 1;console.log(p.a, p.b); // 1, 42

Ici, l'objetProxy définit unecible (ici c'est un objet vide) et un gestionnaire (handler) qui implémente unetrappe pour l'opérationget. Ainsi, l'objet qui est « proxyfié » ne renverra pasundefined lorsqu'on tentera d'accéder à une propriété qui n'est pas définie, à la place le nombre 42 sera renvoyé.

Note :D'autres exemples sont disponibles sur la page de l'objetProxy.

Terminologie

Lorsqu'on utilise les proxies et leurs fonctionnalités, on utilisera les termes suivants :

gestionnaire (handler)

L'objet qui contient les trappes.

trappes

Les méthodes qui fournissent l'accès aux propriétés. Ce concept est analogue aux trappes utilisées dans les systèmes d'exploitations.

cible

L'objet que le proxy virtualise. C'est généralement un objet utilisé en arrière-plan pour stocker les informations. Les invariants (c'est-à-dire les éléments sémantiques qui doivent rester inchangés) concernant le caractère non-extensible de l'objet ou l'aspect non-configurable des propriétés sont vérifiés par rapport à cet objet cible.

invariants

Les éléments sémantiques qui ne doivent pas être modifiés par les opérations définies dans les proxies. Si un invariant n'est pas respecté au sein d'un gestionnaire, cela provoquera une exceptionTypeError.

Les gestionnaires et les trappes

Le tableau suivant résume les différentes trappes disponibles pour les objetsProxy. Pour plus d'explications et de détails, voir les différentspages de la référence sur chacun de ces concepts.

Gestionnaires / TrappesOpérations interceptéesInvariants
handler.getPrototypeOf()Object.getPrototypeOf()
Reflect.getPrototypeOf()
__proto__
Object.prototype.isPrototypeOf()
instanceof
getPrototypeOf doit renvoyer un objet ounull.

Sicible n'est pas extensible,Object.getPrototypeOf(proxy) doit renvoyer le même objet queObject.getPrototypeOf(cible).
handler.setPrototypeOf()Object.setPrototypeOf()
Reflect.setPrototypeOf()

Sicible n'est pas extensible, le paramètreprototype doit être la même valeur queObject.getPrototypeOf(cible).

handler.isExtensible()Object.isExtensible()Reflect.isExtensible()

Object.isExtensible(proxy) doit renvoyer la même valeur queObject.isExtensible(target).

handler.preventExtensions()Object.preventExtensions()Reflect.preventExtensions()

Object.preventExtensions(proxy) ne renvoietrue que siObject.isExtensible(proxy) vautfalse.

handler.getOwnPropertyDescriptor()Object.getOwnPropertyDescriptor()Reflect.getOwnPropertyDescriptor()

getOwnPropertyDescriptor doit renvoyer un objet ouundefined.

Une propriété ne peut pas être vue comme non-existante si elle existe comme une propriété propre non-configurable de l'objet cible.

Une propriété ne peut pas être vue comme non-existante si elle existe comme une propriété propre de la cible et que l'objet cible n'est pas extensible.

Une propriété ne peut pas être vue comme existante si elle n'existe pas comme une propriété propre de l'objet cible et que l'objet cible n'est pas extensible.

Une propriété ne peut pas être vue comme non-configurable si elle n'existe pas comme une propriété propre de l'objet cible ou si elle existe comme une propriété configurable propre de l'objet cible.

Le résultat deObject.getOwnPropertyDescriptor(cible) peut être appliqué à la cible en utilisantObject.defineProperty sans que cela ne lève d'exception.

handler.defineProperty()Object.defineProperty()Reflect.defineProperty()

Une propriété ne peut pas être ajoutée si l'objet cible n'est pas extensible.

Une propriété ne peut pas être ajoutée ou être modifiée afin d'être non-configurable si elle n'existe pas comme une propriété propre de l'objet cible et qu'elle n'est pas non-configurable.

Une propriété peut ne pas être non-configurable si une propriété correspondante configurable existe sur l'objet cible.

Si une propriété possède une propriété correspondante sur l'objet cible,Object.defineProperty(cible, prop, descripteur) ne doit pas renvoyer d'exception.

En mode strict, si la valeur de retour dedefineProperty estfalse, cela entraînera une exceptionTypeError exception.

handler.has()

Requête d'une propriété :toto in proxy

Requête d'une propriété héritée :toto in Object.create(proxy)

Reflect.has()

Une propriété ne peut pas être vue comme non-existante si elle existe comme propriété propre non-configurable de l'objet cible.

Une propriété ne peut pas être vue comme non-existante si elle existe comme propriété propre de l'objet cible et que l'objet cible n'est pas extensible.

handler.get()

Accès à une propriété :proxy[toto] etproxy.truc

Accès à une propriété héritée :Object.create(proxy)[toto]

Reflect.get()

La valeur rapportée pour la propriété doit être la même que la valeur de la propriété correspondante sur l'objet cible si celle-ci est une propriété de donnée non accessible en écriture et non-configurable..

La valeur rapportée pour une propriété doit êtreundefined si la propriété correspondante de l'objet cible est une propriété d'accesseur dont l'attribut [[Get]] vautundefined.

handler.set()

Affection d'une propriété :proxy[toto] = truc etproxy.toto = truc

Affectation d'une propriété héritée :Object.create(proxy)[toto] = truc

Reflect.set()

Il est impossible de modifier la valeur d'une propriété pour que celle-ci soit différente de la valeur de la propriété correspondante de l'objet cible si la propriété de l'objet cible est une propriété de donnée qui n'est pas accessible en écriture et qui n'est pas configurable.

Il est impossible de modifier la valeur d'une propriété si la propriété correspondante de l'objet cible est une propriété d'accesseur non-configurable dont l'attribut [[Set]] vautundefined.

En mode strict, si le gestionnaire pourset renvoiefalse, cela provoquera une exceptionTypeError.

handler.deleteProperty()

Suppression d'une propriété :delete proxy[toto] etdelete proxy.toto

Reflect.deleteProperty()

Une propriété ne peut pas être supprimée si elle existe comme une propriété propre non-configurable de l'objet cible.
handler.enumerate()

Lister les propriétés avecfor...in :for (var nom in proxy) {...}

Reflect.enumerate()

La méthodeenumerate doit renvoyer un objet.
handler.ownKeys()

Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
Reflect.ownKeys()

Le résultat deownKeys est une liste.

Le type de chaque élément de la liste est soit uneString soit unSymbol.

La liste résultatnte doit contenir les clés de toutes les propriétés non-configurables de l'objet cible.

Si l'objet cible n'est pas extensible, la liste résultante doit contenir toutes les clés des propriétés propres de l'objet cibles et aucune autre valeur.

handler.apply()

proxy(..args)

Function.prototype.apply() andFunction.prototype.call()

Reflect.apply()

Il n'y a pas d'invariant pour la méthodehandler.apply.
handler.construct()

new proxy(...args)
Reflect.construct()

Le résultat doit être unObjet.

Proxies révocables

La méthodeProxy.revocable() est utilisée pour créer un objetProxy qui puisse être révoqué. Cela signifie que que le proxy pourra être révoqué avec la fonctionrevoke et arrêtera le proxy. Après cet arrêt, toute opération sur le proxy entraînera une exceptionTypeError.

js
var revocable = Proxy.revocable(  {},  {    get: function (cible, nom) {      return "[[" + nom + "]]";    },  },);var proxy = revocable.proxy;console.log(proxy.toto); // "[[toto]]"revocable.revoke();console.log(proxy.toto); // déclenche une TypeErrorproxy.toto = 1; // une TypeError encoredelete proxy.toto; // toujours une TypeErrortypeof proxy; // "object", typeof ne déclenche aucune trappe

Réflexion

Reflect est un objet natif qui fournit des méthodes pour les opérations JavaScript qui peuvent être interceptées. Ces méthodes sont les mêmes que celles gérées par lesgestionnaires de proxy.Reflect n'est pas un constructeur et ne peut pas être utilisé comme une fonction !

Reflect aide à transférer les opérations par défaut depuis le gestionnaire vers la cible.

Par exemple, avecReflect.has(), on obtient le comportement de l'opérateurin sous forme d'une fonction :

js
Reflect.has(Object, "assign"); // true

Help improve MDN

Learn how to contribute.

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp