Proxy

Последнее обновление: 20.11.2023

Прокси (Proxy) представляет объект, который позволяет перехватывать выполнение операций по отношению к некоторому другому объекту и может переопределять его поведение.

Для создания объекта Proxy применяется конструктор Proxy():

const proxy = new Proxy(target, handler);

Конструктор Proxy принимает два параметра:

  • target - цель создания прокси, это может быть любой объект, к которому применяется Proxy

  • handler - другой объект, который определяет, какие именно операции объекта target будут перехватываться и переопределяться и как именно.

Рассмотрим простейший пример:

// объект, к которому применяется прокси
const target = {name: "Tom"};
// объект, который определяет, как будет переопределяться target
const handler = {};
// объект прокси
const proxy = new Proxy(target, handler);

console.log(proxy.name); 	// Tom

Итак, в примере выше target - это объект, к которому будет применяться проксирование. В данном случае этот объект имеет свойство name.

const target = {name: "Tom"};

Далее создается пустой обработчик handler:

const handler = {};

В принципе этот объект должен определять, как будет переопределяться объект target. Но пока оставим его пустым.

Затем создаем объект Proxy, передавая в его конструктор объекты target и handler.

const proxy = new Proxy(target, handler);

Проксирование объекта (в данном случае объекта target) означает, что через прокси мы можем обращаться к функциональности этого объекта. И в данном случае через объект proxy мы можем обратиться к свойству name проксированного объекта target:

console.log(proxy.name); 	// Tom

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

Переопределение функциональности объекта

Выше мы выполнили проксирование объекта, но пока никак не переопределяли его поведение. Ключевым в данном случае является определение обработчика handler, который может перехватывать обращения к свойствам проксированного объекта. Этот обработчик может определять два метода: get и set.

Метод get и получение свойств объекта

Метод get перехватывает обращения к свойству при получении его значения и возвращает для этого свойства некоторое значение:

const handler = {
  get: function(target, prop, receiver) {
    return некоторое_значение;
  }
};

Метод get имеет три параметра:

  • target: сам проксированный объект. Благодаря этому параметру мы можем обратиться к функциональности оригинального объекта

  • prop: название свойства, к которому идет обращение

  • receiver: объект Proxy, через который выполняется проксирование

Возьмем следующий пример:

const target = {name: "Tom"};
const handler = {
  get: function(target, prop, receiver) {
    return "Tomas Smith";
  }
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); 	// Tomas Smith

Здесь в обработчике handler в методе get возвращается строка "Tomas Smith":

get: function(target, prop, receiver) {
	return "Tomas Smith";
}

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

console.log(proxy.name); 	// Tomas Smith

Так, мы выполнили перехват обращения к свойству и простейшее переопределение. При этом мы можем обащаться и к оригинальному объекту, который проксируется:

const target = {name: "Tom"};
const handler = {
  get: function(target, prop) {
    return "Name: " + target.name;
  }
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); 	// Name: Tom

Здесь обработчик возвращает строку "Name: " + target.name, где target.name представляет обращение к свойству name оригинального объекта. Естественно логика возвращение значения свойства может более сложной.

Но возьмем более сложный объект - с двумя свойствами:

const target = {name: "Tom", age: 37};
const handler = {
  get: function(target, prop) {
    return target[prop];
  }
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); 	// Tom
console.log(proxy.age); 	// 37

Здесь целевой объект имеет два свойства: name и age. В обработчике мы перехватываем обращение к ним, но никак его не переопределяем, а просто возвращаем значения свойств оригинального объекта:

return target[prop];

Для обращения к свойствам целевого объекта применяется синтаксис массивов.

Но также мы можем проверить, к какому именно свойству идет обращение, и выполнить некоторое переопределение:

const target = {name: "Tom", age: 37};
const handler = {
  get: function(target, prop) {
	if(prop==="name")
		return target.name.toUpperCase();
	else
		return target[prop];
  }
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); 	// TOM
console.log(proxy.age); 	// 37

В данном случае, если обращение идет к свойству name, то есть к свойству, которое хранит строку, то вызываем у этой строки метод toUpperCase() и переводим ее в верхний регистр.

Установка свойства и метод set

Метод set перехватывает обращения к свойству при установке его значения:

const handler = {
  set: function(target, property, value, receiver) {
    
  }
};

Метод set имеет четыре параметра:

  • target: оригинальный объект, к которому идет проксирование

  • property: название свойства, к которому идет обращение

  • value: устанавливаемое значение

  • receiver: объект Proxy, через который выполняется проксирование

Рассмотрим на примере:

const target = {name: "Tom", age: 37};
const handler = {
  set: function(target, prop, value) {
		console.log(value);
		target[prop] = value;
  }
};
const proxy = new Proxy(target, handler);
proxy.name = "Tomas";
console.log(proxy.name); 	// Tomas
proxy.age = 22;				
console.log(proxy.age); 	// 22

В данном примере в методе set сначала логирруем передаваеемое свойству значение, затем устанавливаем свойство:

target[prop] = value;

Немного изменим пример:

const target = {name: "Tom", age: 37};
const handler = {
  set: function(target, prop, value) {
	if(prop==="age" && value < 1)
		console.log("Некорректный возраст");
	else
		return target[prop] = value;
  }
};
const proxy = new Proxy(target, handler);
proxy.name = "Tomas";
console.log(proxy.name); 	// Tomas
proxy.age = -199;			// Некорректный возраст
console.log(proxy.age); 	// 37
proxy.age = 22;				
console.log(proxy.age); 	// 22

Здесь в методе set обработчика проверяем, если идет установка свойства age и значение меньше 1, то просто выводим сообщение о некорректности данных

if(prop==="age" && value < 1)
	console.log("Некорректный возраст");

Иначе передаем значение свойству оригинального объекта:

else
	return target[prop] = value;
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850