Прокси-объект может определять поведение всякий раз, когда мы взаимодействуем с объектом, например, когда мы получаем значение или устанавливаем значение.

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

const account = {
  name: "Julio",
  isPremium:false,
  isLogged: true
}

Пользователь не должен иметь возможности изменять свойства входа в систему или тип службы или назначать пустые значения каким-либо свойствам. Мы также должны проверить, не пытается ли пользователь получить доступ к свойству несуществующего объекта, и если да, то сообщить об этом пользователю. И именно здесь имеет смысл использовать прокси, который по сути является вторым объектом, отвечающим за «мониторинг» взаимодействий, которые выполняются на исходном объекте. Что-то вроде агента футболиста или секретаря руководства.

Вместо прямого взаимодействия с этим объектом (футболистом или генеральным директором) мы хотим взаимодействовать с прокси-объектом. В JavaScript мы можем легко создать новый прокси, создав новый экземпляр Proxy.

const accountProxy = new Proxy(account, {});

Второй аргумент Proxy — это объект, представляющий обработчик. В объекте обработчика мы можем определить конкретное поведение в зависимости от типа взаимодействия. Хотя есть много методов, которые вы можете добавить к обработчику Proxy, два самых распространенных — это get и set:

  1. get: вызывается при попытке доступа к свойству.
  2. set: вызывается при попытке изменить свойство

Вместо прямого взаимодействия с объектом account мы будем взаимодействовать с accountProxy.

Добавляем два обработчика в accountProxy accountProxy. Первый, сеттер, будет действовать, когда мы попытаемся изменить свойство. Вызывая метод set на прокси, мы хотим, чтобы прокси зарегистрировал предыдущее значение и новое значение свойства. Второй, геттер, вступает в действие при доступе к свойству. При вызове метода get на прокси мы хотим, чтобы прокси зарегистрировал ключ и значение свойства и сообщил нам об этом через журнал.

const accountProxy = new Proxy(account, {
  get: (obj, prop) => {
    console.log(`The value of ${prop} is ${obj[prop]}`);
  },
  set: (obj, prop, value) => {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    obj[prop] = value;
  }
});
accountProxy.name // The value of name is Julio
accountProxy.isPremium = true // Changed isPremium from false to true

Как мы упоминали ранее, с помощью нашего Proxy мы хотим:

  1. пользователь не должен иметь возможность изменять свойства входа или тип службы
  2. или присвойте пустые значения любому из свойств
  3. и проверить, не пытается ли пользователь получить доступ к свойству объекта, которого не существует, и если да, то сообщить об этом пользователю
const account = {
  name: "Julio",
  isPremium:false,
  isLogged:true
}
const accountProxy = new Proxy(account, {
  get: (obj, prop) => {
    if (!obj[prop]) {
      console.log(
        `This property doesn't exist on the target object`
      );
    } else {
      console.log(`The value of ${prop} is ${obj[prop]}`);
    }
  },
  set: (obj, prop, value) => {
    if (prop === "name" && typeof value !== "string") {
      console.log(`You can only pass string values for name property.`);
    } else if (prop === "name" && !value.length) {
      console.log(`You need to provide a valid name.`);
    } else if(prop === "isPremium"  && typeof value === "boolean"){
      console.log(`You can't modify ${prop} from ${obj[prop]}`);
    }
    else if(prop === "isLogged"  && typeof value === "boolean"  ){
      console.log(`You can't modify ${prop} from ${obj[prop]}`);
    }
  }
});
accountProxy.name= "" // You need to provide a valid name
accountProxy.noExistProp // This property doesn't exist on the target object
accountProxy.isPremium = true // You can't modify isPremium from false

Proxies — это мощный способ добавить контроль над поведением объекта. Прокси может иметь различные варианты использования: он может помочь с проверкой, форматированием, уведомлениями или отладкой.

Чрезмерное использование объекта Proxy или выполнение тяжелых операций при каждом вызове метода handler может легко отрицательно сказаться на производительности вашего приложения. Лучше не использовать прокси для критически важного для производительности кода.

Посмотрите здесь, в бесплатном видео Vue MasteryГреггом Поллаком и Эваном Ю), как Vue 3 реализует шаблон Proxy. Это прекрасно 👌

Я надеюсь, что вы нашли эту статью полезной. В следующем мы углубимся в этот шаблон и включим Reflect API.

Рекомендации