Proxy: перехват и настройка операций над объектами

Что такое Proxy и зачем он нужен? 🤔

Proxy — это мощный механизм в JavaScript, который позволяет создавать "прокси-обёртки" вокруг объектов. С его помощью можно перехватывать и настраивать базовые операции (чтение, запись, удаление свойств и другие).

Представьте, что у вас есть секретарь (прокси), который фильтрует все обращения к вашему календарю (объекту). Вы можете настроить правила: какие встречи добавлять, какие скрывать, или даже подменять информацию!

const target = { name: 'Алексей' };
const handler = {
  get(target, prop) {
    return prop in target ? target[prop] : 'Свойство не найдено!';
  }
};

const proxy = new Proxy(target, handler);
console.log(proxy.name); // "Алексей"
console.logproxy.age);   // "Свойство не найдено!"

Как создать Proxy? 🛠️

Синтаксис прост:

const proxy = new Proxy(target, handler);
  • target — исходный объект, который нужно обернуть
  • handler — объект-ловушка, содержащий методы для перехвата операций

🔥 Важно! Сам target не изменяется — все операции происходят через прокси. Если нужно изменить оригинал, делайте это явно в ловушках.


Основные ловушки (traps) 🎣

Вот самые полезные ловушки, которые можно определить в handler:

Ловушка Когда срабатывает Пример использования
get При чтении свойства Валидация доступа
set При записи свойства Проверка значений
has При операции in Скрытие свойств
deleteProperty При удалении свойства Запрет удаления
apply При вызове функции (если target — функция) Мемоизация

Практические примеры ✨

1. Валидация значений

Запретим устанавливать отрицательный возраст:

const person = { name: 'Мария', age: 30 };

const validator = {
  set(target, prop, value) {
    if (prop === 'age' && value < 0) {
      throw new Error('Возраст не может быть отрицательным!');
    }
    target[prop] = value;
    return true;
  }
};

const proxy = new Proxy(person, validator);
proxy.age = -5; // Выбросит ошибку

2. Ленивая загрузка свойств

Загружаем тяжелые данные только при обращении:

const heavyData = {
  get bigData() {
    console.log('Загружаем тяжелые данные...');
    return /* данные из API */;
  }
};

const lazyLoader = {
  get(target, prop) {
    return prop in target ? target[prop] : null;
  }
};

const proxy = new Proxy(heavyData, lazyLoader);
console.log(proxy.bigData); // Загрузит данные только сейчас

Продвинутые техники 🚀

Proxy для функций

Можно перехватывать и вызовы функций!

function sum(a, b) {
  return a + b;
}

const logger = {
  apply(target, thisArg, args) {
    console.log(`Вызов функции с аргументами: ${args}`);
    return target.apply(thisArg, args);
  }
};

const loggedSum = new Proxy(sum, logger);
loggedSum(2, 3); // Логирует вызов и возвращает 5

"Несуществующие" свойства

Создадим объект, который возвращает значения для любых свойств:

const magic = new Proxy({}, {
  get(target, prop) {
    return `Вы запросили: ${prop}`;
  }
});

console.log(magic.anything); // "Вы запросили: anything"
console.log(magic.hello);    // "Вы запросили: hello"

Ограничения и подводные камни ⚠️

  1. Нельзя перехватить некоторые операции (например, строгое равенство ===).
  2. Производительность — прокси добавляют накладные расходы, не используйте их для критичного по скорости кода.
  3. Прозрачностьtypeof proxy возвращает 'object', как и для обычного объекта.

💡 Совет от Данилы Бежина: используйте прокси для задач высокого уровня (валидация, логирование, доступ), а не для базовой логики приложения.


Где это применяется на практике? 🌍

  1. Валидация данных (формы, API-ответы)
  2. Логирование и отладка сложных взаимодействий
  3. Роутеры в SPA-фреймворках
  4. ORM-библиотеки для ленивой загрузки данных
  5. Системы реактивности (как во Vue 3)
// Пример реактивности
const reactive = (obj) => {
  return new Proxy(obj, {
    set(target, prop, value) {
      target[prop] = value;
      console.log(`Изменено: ${prop} = ${value}`);
      return true;
    }
  });
};

const state = reactive({ count: 0 });
state.count++; // Логирует: "Изменено: count = 1"

Подведём итоги 🎓

Proxy — это:

  • 🔮 Виртуальный слой поверх объектов
  • 🛡️ Инструмент для контроля доступа и изменений
  • 🧩 Основа для сложных абстракций
  • ⚖️ Баланс между мощью и производительностью

Попробуйте применить прокси в своём коде — вы удивитесь, сколько задач они могут элегантно решить!

Скрыть рекламу навсегда

🧠 Учёба без воды и зубрёжки

Закрытый Boosty с наработками опытного преподавателя.

Объясняю сложное так, чтобы щелкнуло.

🚀 Забрать доступ к Boosty