En termes informatiques, les proxies s'interposent entre vous et les éléments avec lesquels vous communiquez. Le terme est le plus souvent appliqué à un serveur proxy – un périphérique entre le navigateur Web (Chrome, Firefox, Safari, Edge, etc.) et le serveur Web (Apache, Nginx, IIS, etc.) où se trouve une page. Le serveur proxy peut modifier les demandes et les réponses. Par exemple, il peut augmenter l'efficacité en mettant en cache les ressources régulièrement consultées et en les diffusant auprès de plusieurs utilisateurs.
Les proxys ES6 se trouvent entre votre code et un objet. Un proxy vous permet d'effectuer des opérations de métaprogrammation telles que l'interception d'un appel pour inspecter ou modifier la propriété d'un objet.
La terminologie suivante est utilisée pour les proxys ES6:
target
L'objet original le proxy va virtualiser. Cela pourrait être un objet JavaScript tel que la bibliothèque jQuery ou des objets natifs tels que des tableaux ou même d'autres proxies
handler
Un objet qui implémente le comportement du proxy en utilisant …
traps
] Fonctions définies dans le gestionnaire qui permettent d'accéder à la cible lorsque des propriétés ou des méthodes spécifiques sont appelées
Il est préférable de l'expliquer par un exemple simple. Nous allons créer un objet cible nommé target
qui a trois propriétés:
const target = {
a: 1,
b: 2,
c: 3
}
Nous allons maintenant créer un objet handler qui intercepte toutes les opérations get
. Cela retourne la propriété de la cible quand elle est disponible ou 42 sinon:
const handler = {
get: function (cible, nom) {
revenir (
nom dans la cible? Cible [name]: 42
)
}
}
Nous créons maintenant un nouveau proxy en passant les objets target et handler. Notre code peut interagir avec le proxy plutôt que d'accéder directement à l'objet cible
:
const proxy = new Proxy (target, handler);
console.log (proxy.a); // 1
console.log (proxy.b); // 2
console.log (proxy.c); // 3
console.log (proxy.meaningOfLife); // 42
Développons le gestionnaire proxy de manière à ce qu'il ne permette que les propriétés à un caractère de a
à z
à définir:
const handler = {
get: function (cible, nom) {
return (nom dans la cible? target [name]: 42);
},
set: function (cible, prop, valeur) {
if (prop.length == 1 && prop> = 'a' && prop <= 'z') {
cible [prop] = valeur;
retourner vrai;
}
autre {
throw new ReferenceError (prop + 'ne peut pas être défini');
return false;
}
}
}
const proxy = new Proxy (cible, gestionnaire);
proxy.a = 10;
proxy.b = 20;
proxy.ABC = 30;
// Exception: ReferenceError: ABC ne peut pas être défini
Types de pièges proxy
Nous avons vu le obtenir
et définir
en action, qui sont susceptibles d'être les pièges les plus utiles. Cependant, il existe plusieurs autres types de pièges que vous pouvez utiliser pour compléter le code du gestionnaire de proxy:
- construct (target, argList)
Intercepte la création d'un nouvel objet avec l'opérateur
TrapsObject.get ()
et doit renvoyer la valeur de la propriété - set (target, property, value)
TrapsObject.set ( )
et doit définir la valeur de la propriété. Retourtrue
en cas de succès. En mode strict, renvoyerfalse
lancera une exception TypeError - deleteProperty (target, property)
Intercepte une opérationdelete
sur la propriété d'un objet. Doit retourner soitvrai
soitfaux
. - apply (cible, thisArg, argList)
Traps appels de fonction d'objet. - has (target, property)
Trapsdans
opérateurs et doit renvoyer soittrue
soitfalse
. - ownKeys (cible)
TrapsObject.getOwnPropertyNames ()
et doit retourner un objet énumérable - getPrototypeOf (target)
TrapsObject.getPrototypeOf ()
et doit renvoyer l'objet du prototype ou null - setPrototypeOf (target, prototype)
] InterruptionsObject.setPrototypeOf ()
pour définir l'objet prototype. - isExtensible (target)
TrapsObject.isExtensible ()
qui détermine si un objet peut avoir de nouvelles propriétés ajoutées. Doit retournertrue
oufalse
. - preventExtensions (target)
TrapsObject.preventExtensions ()
qui empêche l'ajout de nouvelles propriétés à un objet. Doit retourner soittrue
soitfalse
. - getOwnPropertyDescriptor (cible, propriété)
TrapsObject.getOwnPropertyDescriptor ()
qui renvoie undefined ou une propriété objet descripteur avec des attributs pourvaleur
inscriptible
get
ensemble
configurable
eténumérable
- defineProperty (cible, propriété, descripteur)
TrapsObject.defineProperty ()
qui définit ou modifie une propriété d'objet. Doit retournertrue
si la propriété target a été définie avec succès oufalse
sinon
Proxy Example 1: Profiling
Les proxies vous permettent de créer des wrappers génériques pour n'importe quel objet sans avoir pour modifier le code dans les objets cibles eux-mêmes.
Dans cet exemple, nous allons créer un proxy de profilage qui compte le nombre de fois où une propriété est accédée. Tout d'abord, nous avons besoin d'une fonction d'usine makeProfiler
qui renvoie l'objet Proxy
et conserve l'état de comptage:
// créer un proxy de profilage
function makeProfiler (cible) {
const
compte = {},
gestionnaire = {
get: function (cible, nom) {
if (nom dans la cible) {
compte [name] = (compte [name] || 0) + 1;
cible de retour [name];
}
}
}
revenir {
proxy: nouveau proxy (cible, gestionnaire),
compter: compter
}
}
Nous pouvons maintenant appliquer ce wrapper de proxy à n'importe quel objet ou un autre proxy. Par exemple:
const myObject = {
h: 'Bonjour',
w: 'Monde'
}
// crée un proxy myObject
const pObj = makeProfiler (monObjet);
// accéder aux propriétés
console.log (pObj.proxy.h); // Bonjour
console.log (pObj.proxy.h); // Bonjour
console.log (pObj.proxy.w); // Monde
console.log (pObj.count.h); // 2
console.log (pObj.count.w); // 1
Bien que ce soit un exemple trivial, imaginez l'effort requis si vous deviez effectuer des comptages d'accès aux propriétés dans plusieurs objets différents sans utiliser de proxy
Exemple de proxy 2: Liaison de données bidirectionnelle
Il est généralement utilisé dans les bibliothèques MVC JavaScript pour mettre à jour un objet interne lorsque le DOM change et vice versa.
Supposons que nous ayons un champ de saisie avec un ID de inputname
:
Nous avons aussi un objet JavaScript nommé myUser
avec une propriété id
qui fait référence à cette entrée:
// état interne pour le champ #inputname
const myUser = {
id: 'nom d'entrée',
prénom: ''
}
Notre premier objectif est de mettre à jour myUser.name
lorsqu'un utilisateur modifie la valeur d'entrée. Cela peut être réalisé avec un gestionnaire d'événement onchange
sur le champ:
inputChange (myUser);
// lie l'entrée à l'objet
function inputChange (monObjet) {
if (! myObject ||! myObject.id) renvoie;
const input = document.getElementById (monObjet.id);
input.addEventListener ('onchange', fonction (e) {
myObject.name = input.value;
});
}
Notre prochain objectif est de mettre à jour le champ de saisie lorsque nous modifions myUser.name
dans le code JavaScript. Ce n'est pas aussi simple, mais les proxies offrent une solution:
// gestionnaire de proxy
const inputHandler = {
set: function (target, prop, nouvelleValeur) {
if (prop == 'nom' && target.id) {
// mise à jour de la propriété
target [prop] = nouvelle valeur;
// met à jour la valeur du champ d'entrée
document.getElementById (target.id) .value = nouvelleValeur;
retourner vrai;
}
sinon, retournez faux;
}
}
// crée un proxy
const myUserProxy = nouveau proxy (myUser, inputHandler);
// définir un nouveau nom
myUserProxy.name = 'Craig';
console.log (myUserProxy.name); // Craig
console.log (document.getElementById ('nom d'entrée'). value); // Craig
Cela peut ne pas être l'option de liaison de données la plus efficace, mais les proxies vous permettent de modifier le comportement de nombreux objets existants sans changer leur code
Hemanth.HM's article Negative Array Index en JavaScript suggère d'utiliser des proxies pour implémenter des index de tableaux négatifs. Par exemple, arr [-1]
renvoie le dernier élément, arr [-2]
renvoie l'avant-dernier élément, et ainsi de suite
arr [-1]
renvoie le dernier élément, arr [-2]
renvoie l'avant-dernier élément, et ainsi de suite
L'article de Nicholas C. Zakas propriétés de sécurité avec des proxies ECMAScript 6 illustre comment les proxies peuvent être utilisés pour implémenter la sécurité de type en validant de nouvelles valeurs. Dans l'exemple ci-dessus, nous pouvions vérifier myUserProxy.name
était toujours défini sur une chaîne et renvoyer une erreur sinon
Proxy Support
Le pouvoir des proxies n'est peut-être pas évident, mais ils offrent puissantes opportunités de méta-programmation. Brendan Eich, le créateur de JavaScript, pense Proxies are Awesome !
Actuellement, le support de proxy est implémenté dans Node et tous les navigateurs actuels, à l'exception d'Internet Explorer 11. Cependant, s'il vous plaît noter que tous les navigateurs supportent tous les pièges. Vous pouvez avoir une meilleure idée de ce qui est supporté en consultant cette table de compatibilité du navigateur sur la page MDN Proxy
Malheureusement, il n'est pas possible de polyfill ou transpile le code proxy ES6 en utilisant des outils tels que parce que les proxies sont puissants et n'ont pas d'équivalent ES5.
Source link