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 можно на коленке собрать «мидлвари» для объектов, массивов и функций, в общем-то, с любыми целями.