[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/fr/docs/Web/JavaScript/Guide/Meta_programming [Back]  [Original]

Mtaprogrammation - JavaScript | MDN

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

View in English Always switch to English

Mtaprogrammation

partir d'ECMAScript 2015, JavaScript fournit les objets natifs Proxy et Reflect. Ces objets permettent d'intercepter et de dfinir des comportements spcifiques pour certaines oprations fondamentales du langage (par exemple la recherche d'une proprit, l'affectation, l'numration, l'appel d'une fonction, etc.). Grce ces deux objets, il est possible d'interagir avec le langage lui-mme (on parle alors de mtaprogrammation).

Dans cet article

Les proxies

Introduits avec ECMAScript 2015, les objets Proxy permettent d'intercepter certaines oprations JavaScript et de dfinir le comportement avoir quand celles-ci se produisent. Par exemple, on peut intercepter l'accs une proprit 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'objet Proxy dfinit une cible (ici c'est un objet vide) et un gestionnaire (handler) qui implmente une trappe pour l'opration get. Ainsi, l'objet qui est proxyfi ne renverra pas undefined lorsqu'on tentera d'accder une proprit qui n'est pas dfinie, la place le nombre 42 sera renvoy.

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

Terminologie

Lorsqu'on utilise les proxies et leurs fonctionnalits, on utilisera les termes suivants :

gestionnaire (handler)

L'objet qui contient les trappes.

trappes

Les mthodes qui fournissent l'accs aux proprits. Ce concept est analogue aux trappes utilises dans les systmes d'exploitations.

cible

L'objet que le proxy virtualise. C'est gnralement un objet utilis en arrire-plan pour stocker les informations. Les invariants (c'est--dire les lments smantiques qui doivent rester inchangs) concernant le caractre non-extensible de l'objet ou l'aspect non-configurable des proprits sont vrifis par rapport cet objet cible.

invariants

Les lments smantiques qui ne doivent pas tre modifis par les oprations dfinies dans les proxies. Si un invariant n'est pas respect au sein d'un gestionnaire, cela provoquera une exception TypeError.

Les gestionnaires et les trappes

Le tableau suivant rsume les diffrentes trappes disponibles pour les objets Proxy. Pour plus d'explications et de dtails, voir les diffrents pages de la rfrence sur chacun de ces concepts.

Gestionnaires / Trappes Oprations interceptes Invariants
handler.getPrototypeOf() Object.getPrototypeOf()
Reflect.getPrototypeOf()
__proto__
Object.prototype.isPrototypeOf()
instanceof
getPrototypeOf doit renvoyer un objet ou null.

Si cible n'est pas extensible, Object.getPrototypeOf(proxy) doit renvoyer le mme objet que Object.getPrototypeOf(cible).
handler.setPrototypeOf() Object.setPrototypeOf()
Reflect.setPrototypeOf()

Si cible n'est pas extensible, le paramtre prototype doit tre la mme valeur que Object.getPrototypeOf(cible).

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

Object.isExtensible(proxy) doit renvoyer la mme valeur que Object.isExtensible(target).

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

Object.preventExtensions(proxy) ne renvoie true que si Object.isExtensible(proxy) vaut false.

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

getOwnPropertyDescriptor doit renvoyer un objet ou undefined.

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

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

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

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

Le rsultat de Object.getOwnPropertyDescriptor(cible) peut tre appliqu la cible en utilisant Object.defineProperty sans que cela ne lve d'exception.

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

Une proprit ne peut pas tre ajoute si l'objet cible n'est pas extensible.

Une proprit ne peut pas tre ajoute ou tre modifie afin d'tre non-configurable si elle n'existe pas comme une proprit propre de l'objet cible et qu'elle n'est pas non-configurable.

Une proprit peut ne pas tre non-configurable si une proprit correspondante configurable existe sur l'objet cible.

Si une proprit possde une proprit correspondante sur l'objet cible, Object.defineProperty(cible, prop, descripteur) ne doit pas renvoyer d'exception.

En mode strict, si la valeur de retour de defineProperty est false, cela entranera une exception TypeError exception.

handler.has()

Requte d'une proprit : toto in proxy

Requte d'une proprit hrite : toto in Object.create(proxy)

Reflect.has()

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

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

handler.get()

Accs une proprit : proxy[toto] et proxy.truc

Accs une proprit hrite : Object.create(proxy)[toto]

Reflect.get()

La valeur rapporte pour la proprit doit tre la mme que la valeur de la proprit correspondante sur l'objet cible si celle-ci est une proprit de donne non accessible en criture et non-configurable..

La valeur rapporte pour une proprit doit tre undefined si la proprit correspondante de l'objet cible est une proprit d'accesseur dont l'attribut [[Get]] vaut undefined.

handler.set()

Affection d'une proprit : proxy[toto] = truc et proxy.toto = truc

Affectation d'une proprit hrite : Object.create(proxy)[toto] = truc

Reflect.set()

Il est impossible de modifier la valeur d'une proprit pour que celle-ci soit diffrente de la valeur de la proprit correspondante de l'objet cible si la proprit de l'objet cible est une proprit de donne qui n'est pas accessible en criture et qui n'est pas configurable.

Il est impossible de modifier la valeur d'une proprit si la proprit correspondante de l'objet cible est une proprit d'accesseur non-configurable dont l'attribut [[Set]] vaut undefined.

En mode strict, si le gestionnaire pour set renvoie false, cela provoquera une exception TypeError.

handler.deleteProperty()

Suppression d'une proprit : delete proxy[toto] et delete proxy.toto

Reflect.deleteProperty()

Une proprit ne peut pas tre supprime si elle existe comme une proprit propre non-configurable de l'objet cible.
handler.enumerate()

Lister les proprits avec for...in : for (var nom in proxy) {...}

Reflect.enumerate()

La mthode enumerate doit renvoyer un objet.
handler.ownKeys()

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

Le rsultat de ownKeys est une liste.

Le type de chaque lment de la liste est soit une String soit un Symbol.

La liste rsultatnte doit contenir les cls de toutes les proprits non-configurables de l'objet cible.

Si l'objet cible n'est pas extensible, la liste rsultante doit contenir toutes les cls des proprits propres de l'objet cibles et aucune autre valeur.

handler.apply()

proxy(..args)

Function.prototype.apply() and Function.prototype.call()

Reflect.apply()

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

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

Le rsultat doit tre un Objet.

Proxies rvocables

La mthode Proxy.revocable() est utilise pour crer un objet Proxy qui puisse tre rvoqu. Cela signifie que que le proxy pourra tre rvoqu avec la fonction revoke et arrtera le proxy. Aprs cet arrt, toute opration sur le proxy entranera une exception TypeError.

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); // dclenche une TypeError
proxy.toto = 1; // une TypeError encore
delete proxy.toto; // toujours une TypeError
typeof proxy; // "object", typeof ne dclenche aucune trappe

Rflexion

Reflect est un objet natif qui fournit des mthodes pour les oprations JavaScript qui peuvent tre interceptes. Ces mthodes sont les mmes que celles gres par les gestionnaires de proxy. Reflect n'est pas un constructeur et ne peut pas tre utilis comme une fonction !

Reflect aide transfrer les oprations par dfaut depuis le gestionnaire vers la cible.

Par exemple, avec Reflect.has(), on obtient le comportement de l'oprateur in sous forme d'une fonction :

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

Web Proxy Viewer  |  New URL  |  Original Page