Proxy и мемоизация функции
Есть такая платформенная штука — Proxy. Это когда берёшь обычный объект в JS, создаёшь для него прокси и получаешь возможность перехватывать и переопределять основные операции, которые с объектом можно совершить: get, set, delete… Внутри перехватчиков можно, например, логировать, валидировать или дополнять значения. Например:
const target = { message1: "hello", message2: "everyone",};
const handler = { get(target, prop, receiver) { console.log(`Свойство ${prop} считалось`); return target[prop]; }, set(target, prop, value) { console.log(`Свойству ${prop} задано значение ${value}`); target[prop] = value; return true; },};
const proxiedObj = new Proxy(target, handler);
proxiedObj.message1;// log: Свойство message1 считалось
proxiedObj.message2 = "nobody";// log: Свойству message2 задано значение nobodyТак вот, проксировать можно не только объекты, но и функции. В случае функций через прокси можно перехватывать момент вызова функции (перехватчик apply) и, например, манипулировать аргументами до вызова.
const a = () => { // функция};
const b = new Proxy(a, { apply: (target, thisArg, argumentsList) => { // перехватчик вызова },});До вызова функции мы получаем референс на саму функцию, контекст и массив агрументов и можем с ними делать что угодно перед тем, как непосредственно вызвать (или даже не вызвать) функцию. К примеру, можно организовать кэш, чтобы по переданному набору аргументов запомнить вычисленное значение и при повторном вызове брать его из кэша.
function memoize(target) { const cache = new Map();
return new Proxy(target, { apply: (target, thisArg, argumentsList) => { const key = JSON.stringify(argumentsList); if (cache.has(key)) { console.log(`Результат для ${argumentsList} взят из кэша`); return cache.get(key); } else { const result = target.apply(thisArg, argumentsList); cache.set(key, result); return result; } }, });
const add = (a, b) => a + b; const memoizedAdd = memoize(add);
memoizedAdd(3, 7); // Вычисляет и записывает в кэш memoizedAdd(3, 7); // Берёт результат из кэша}Аргументами функции, то есть и ключами в кэше могут быть не только примитивы, но и объекты, за счёт того, что ключ формируется с помощью JSON.stringify.
Таким образом, с помощью Proxy можно на коленке собрать «мидлвари» для объектов, массивов и функций, в общем-то, с любыми целями.