Прокси в JavaScript — мощный инструмент, позволяющий создавать «ловушки» для объектов, функций и классов. Тема обширна, поэтому разберем её в двух частях. Эта часть посвящена теории, практическое применение будет рассмотрено во второй части.
Объекты и Proxy
Создадим обычный объект person:
const person = {
name: 'Владилен',
age: 25,
job: 'Full stack'
};
Теперь запроектируем этот объект с помощью Proxy:
const proxy = new Proxy(person, {
get: (target, prop) => {
console.log('getting', prop); // Ловушка для метода get
return target[prop];
}
});
Обращаясь к proxy.name или proxy.age, мы получим значения из объекта person, но при этом сработает наша «ловушка» get, выводящая информацию в консоль. Идея Proxy заключается в перехвате операций над объектом и возможности модификации их поведения.
Proxy предоставляет несколько методов для перехвата различных операций:
- get: Перехватывает чтение свойства объекта.
- set: Перехватывает попытки изменения значений свойств объекта. Можно добавить валидацию или другие действия перед изменением. Пример:
set: (target, prop, value) => {
if (prop in target) {
target[prop] = value;
} else {
throw new Error(`New prop field ${prop} in target`);
}
return true;
},
- has (in): Проверяет существование свойства в объекте. Позволяет реализовать кастомную логику проверки. Пример:
has: (target, prop) => {
const allowedProps = ['name', 'age', 'job'];
return allowedProps.includes(prop);
},
- deleteProperty: Перехватывает удаление свойства. Можно добавить логирование или другие действия. Пример:
deleteProperty: (target, prop) => {
console.log('deleting', prop);
delete target[prop];
return true;
},
Полная документация по методам Proxy доступна по ссылке (ссылка будет добавлена в соответствующее место).
Функции и Proxy
Рассмотрим пример проксирования функции:
function log(text) {
return `log: ${text}`;
}
const fnProxy = new Proxy(log, {
apply: (target, thisArg, args) => {
console.log('calling fn');
const result = target.apply(thisArg, args);
return result.toUpperCase(); // Преобразуем результат в верхний регистр
}
});
Метод apply перехватывает вызов функции. Мы можем выполнить дополнительную логику до или после вызова исходной функции и изменить результат.
Классы и Proxy
Проксирование классов позволяет перехватывать создание новых экземпляров:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const PersonProxy = new Proxy(Person, {
construct: (target, args) => {
console.log('construct');
return new target(...args);
}
});
Метод construct перехватывает вызов оператора new. Мы можем добавить логирование или выполнить другие действия перед созданием экземпляра класса. Можно использовать и другие методы Proxy, например, get для перехвата доступа к свойствам экземпляра.
Динамическое построение ключей
Рассмотрим пример нестандартного использования get:
// ... (код Proxy с get) ...
get: (target, prop) => {
if (!(prop in target)) {
const parts = prop.split('_');
let result = '';
for (const part of parts) {
result += target[part] + ' ';
}
return result.trim();
}
return target[prop];
},
Этот код позволяет динамически создавать значения свойств, если запрашиваемое свойство отсутствует. Например, proxy.name_age_job вернет конкатенацию значений свойств name, age и job.
Proxy — мощный инструмент для расширения функциональности объектов, функций и классов в JavaScript. Он позволяет перехватывать различные операции и добавлять кастомную логику. Во второй части мы рассмотрим практическое применение Proxy.