Proxy ES6 en pratique

Avec l'apparition d'ECMAScript 2015, une avalanche de fonctionnalités est arrivée; certains vous rendent fou, et d'autres sont d'agréables surprises, comme rencontrer un vieil ami après une longue période.


Certaines fonctionnalités sont liées à la métaprogrammation. Qu'est-ce que c'est? Je ne suis pas très éloquent, alors tournons-nous vers notre ami, Wikipedia.


La métaprogrammation est une technique de programmation dans laquelle les programmes informatiques ont la capacité de traiter d'autres programmes comme leurs données. Cela signifie qu'un programme peut être conçu pour lire, générer, analyser ou transformer d'autres programmes, et même se modifier en cours d'exécution. Dans certains cas, cela permet aux programmeurs de minimiser le nombre de lignes de code pour exprimer une solution, réduisant ainsi le temps de développement. Il permet également aux programmes une plus grande flexibilité pour gérer efficacement de nouvelles situations sans recompilation.

En un mot, la métaprogrammation permet à un programme de manipuler les autres ou eux-mêmes au moment de la compilation et de l'exécution. La métaprogrammation en JavaScript est basée sur deux fonctionnalités: Proxy et Reflect API. Dans cet article, nous examinerons le premier.


Proxy


Le proxy est une nouvelle API qui permet d'intercepter, de modifier et d'étendre des objets lors de l'exécution. En utilisant cette API, vous pouvez:


  • Profils de profil et de débogage,
  • Intercepter les appels aux propriétés,
  • Valider "à la volée",
  • etc.

Le proxy est un constructeur qui accepte deux paramètres: l'objet source et l'objet qui agit comme gestionnaire pour l'objet source. Ce dernier contient des méthodes connues sous le nom de pièges.



Un piège est une méthode qui modifie le comportement d'une partie de l'objet. Par exemple, le piège obtient et définit l'interception des appels aux propriétés pour obtenir et établir une valeur respectivement, en pouvant placer la logique avant et pendant ce processus.


Pour mieux comprendre l'utilité des procurations, faisons quelques petits exercices.


Exemple: journalisation / profilage


Imaginez, vous avez 17 ans, vous êtes déjà sur le point d'avoir 18 ans. Et vous voulez que votre programme vous félicite automatiquement lorsque vous l'ouvrez. Pour cela, vous pouvez utiliser Proxy.


et person = { name: "John Doe", age: 17 }; person = new Proxy(person, { set(target, property, value) { if (value === 18) { console.log("Congratulations! You are of legal age"); Reflect.set(target, property, value); return true; } } }); person.age = 18; Not only can we do logs, as I said at the beginning, we can do as far as the language limits us. Here we could make validations for the age, for example, if it exceeds 100 that throw us an error: if (value < 13 && value > 99) { throw new Error('The age should be between 13 and 99') } else { Reflect.set(target, property, value) } Example: secure access to properties let person = { name: "John Doe" }; const Undefined = new Proxy( {}, { get(target, name, receiver) { return Undefined; } } ); const Safeish = obj => { return new Proxy(obj, { get(target, property, receiver) { if (target.hasOwnProperty(property)) { const isObject = target[property] instanceof Object; return isObject ? Safeish(target[property]) : Reflect.get(target, property, receiver); } return Undefined; } }); }; person = Safeish(person); console.log(person.name); console.log(person.sister.name === Undefined); 

Exemple: tableau de requêtes


Nous avons déjà vu un exemple, avec les pièges get et set les plus utilisés. Pour renforcer, allons un peu plus loin et utilisons des proxys imbriqués. Cet exercice va essayer de convertir un tableau conventionnel en un tableau interrogeable pour utiliser des opérateurs comme le SQL groupBy classique.


Pour cela, nous aurons besoin de deux paramètres d'entrée:


  • collection: tableau d'objets que nous allons étendre.
  • groupKeys: tableau de chaînes qui représentent les propriétés pour lesquelles vous allez grouper (nom, catégorie, prix, etc.)

 const data = [ { id: 1, category: 2, name: "Intel NUC Hades Canyon" }, { id: 2, category: 1, name: "Logitech K380" }, { id: 3, category: 1, name: "Genius ECO-8100" } ]; const groupable = (collection, groupKeys) => { // Check that the collection is an array if (!(collection instanceof Array)) { throw new TypeError("The input collection is not an Array"); } const data = JSON.parse(JSON.stringify(collection)); const clone = JSON.parse(JSON.stringify(collection)); Object.defineProperty(clone, "groupBy", { configurable: true, enumerable: false, writable: false, value: groupKeys.reduce((acc, cur) => { acc[cur] = null; return acc; }, {}) }); 

  return new Proxy(clone, { get(target, property, receiver) { if (property === "groupBy") { return new Proxy(target[property], { get(target, property, receiver) { // if the property to be grouped does not exist // log a warning and return [] if (!target.hasOwnProperty(property)) { return []; } // Otherwise, group by property return data.reduce(function(acc, cur) { (acc[cur[property]] = acc[cur[property]] || []).push(cur); return acc; }, {}); } }); } return Reflect.get(target, property, receiver); } }); }; const datasource = groupable(data, ["category"]); console.log(datasource.groupBy.category); 

Conclusions


Le proxy n'est peut-être pas la fonctionnalité ES6 la plus utilisée, mais avec l'API Reflect, c'est l'une des plus importantes et intéressantes. Sa flexibilité permet de l'adopter dans une multitude de cas et, surtout, il est facile à mettre en œuvre.


Les références


https://es.wikipedia.org/wiki/Metaprogramaci%C3%B3n

Source: https://habr.com/ru/post/fr448214/


All Articles