Перейти к содержимому

79. Proxy

Иллюстрация к уроку Proxy в JavaScript - это мощный инструмент для перехвата и изменения базовых операций с объектами. Он позволяет нам контролировать доступ к свойствам, методы и другие аспекты объекта, открывая двери для гибкой настройки поведения.

Представьте себе Proxy как посредника между вами и объектом. Вы обращаетесь к объекту через Proxy, и Proxy решает, как обработать ваш запрос. Это позволяет нам добавлять логику перед тем, как операции чтения, записи или удаления будут выполнены с исходным объектом.

const target = {
name: "Обычный Объект",
age: 30
};
const handler = {
get: function(target, property, receiver) {
console.log(`Попытка чтения свойства: ${property}`);
return Reflect.get(target, property, receiver); // Обязательно использовать Reflect
},
set: function(target, property, value, receiver) {
console.log(`Попытка записи свойства: ${property} со значением: ${value}`);
target[property] = value;
return true; // Важно вернуть true при успешной записи
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // Вывод: "Попытка чтения свойства: name", "Обычный Объект"
proxy.age = 35; // Вывод: "Попытка записи свойства: age со значением: 35"
console.log(target.age); // Вывод: 35 (значение в исходном объекте изменено)

В этом примере handler содержит методы get и set, которые перехватывают операции чтения и записи свойств. Reflect.get и Reflect.set используются для корректного выполнения операций с исходным объектом. Важно использовать Reflect, чтобы избежать проблем с контекстом this и наследованием.

  1. Валидация данных:
const validator = {
set: function(obj, prop, value) {
if (prop === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('Возраст должен быть числом');
}
if (value < 0) {
throw new TypeError('Возраст не может быть отрицательным');
}
}
obj[prop] = value;
return true;
}
};
const person = new Proxy({}, validator);
person.age = 30;
console.log(person.age); // 30
try {
person.age = -10; // Выбросит ошибку
} catch (e) {
console.error(e);
}
  1. Логирование доступа к свойствам:
const logHandler = {
get: function(target, property) {
console.log(`Доступ к свойству: ${property}`);
return target[property];
}
};
const data = { name: "Иван", city: "Москва" };
const loggedData = new Proxy(data, logHandler);
console.log(loggedData.name); // Вывод: "Доступ к свойству: name", "Иван"

Proxy активно используется во фреймворках, таких как Vue.js и MobX, для реализации реактивности. Они перехватывают изменения данных и автоматически обновляют пользовательский интерфейс. Например, Vue.js использует Proxy (или Object.defineProperty в старых браузерах) для отслеживания изменений в данных компонента и перерисовки соответствующих частей DOM.

В некоторых библиотеках для работы с API Proxy используется для создания “ленивых” объектов, которые загружают данные только при первом обращении к ним.

  • Proxy позволяет перехватывать и изменять базовые операции с объектами.
  • Reflect используется для корректного выполнения операций с исходным объектом.
  • Proxy полезен для валидации данных, логирования, реактивности и других задач.
  • get, set, deleteProperty, has, construct, apply - это лишь некоторые из доступных обработчиков Proxy.
  • Не все браузеры поддерживают Proxy (особенно старые версии), поэтому необходимо учитывать совместимость.