27-10-24 12:03:06
Прокси — это объект, который оборачивает другой объект (называемый целью) и позволяет вам перехватывать и изменять его основные операции. Эти операции включают доступ к свойствам, их установку, удаление, вызов функций и другие. С помощью прокси можно контролировать, как объект будет себя вести при выполнении этих операций.
Конструктор Proxy принимает два аргумента:
Вот простой пример, иллюстрирующий использование прокси:
// Целевой объект
const target = {
message: "Привет, мир!"
};
// Обработчик с пользовательской ловушкой 'get'
const handler = {
get: function (obj, prop) {
if (prop in obj) {
return obj[prop];
} else {
return `Свойство "${prop}" не существует.`;
}
}
};
// Создание прокси
const proxy = new Proxy(target, handler);
console.log(proxy.message); // Вывод: Привет, мир!
console.log(proxy.nonExistentProp); // Вывод: Свойство "nonExistentProp" не существует.
В этом примере:
Вот несколько распространенных ловушек, которые можно использовать в обработчике прокси:
Давайте рассмотрим пример, в котором мы перехватываем как чтение, так и запись свойства.
const user = {
name: "Джон"
};
const handler = {
get(target, prop) {
console.log(`Доступ к свойству: ${prop}`);
return prop in target ? target[prop] : "Свойство не существует";
},
set(target, prop, value) {
if (typeof value === 'string') {
console.log(`Установка свойства: ${prop} на значение ${value}`);
target[prop] = value;
return true;
} else {
console.log(`Не удалось установить свойство: ${prop}. Значение должно быть строкой.`);
return false;
}
}
};
const proxyUser = new Proxy(user, handler);
console.log(proxyUser.name); // Вывод: Доступ к свойству: name \n Джон
proxyUser.age = 25; // Вывод: Не удалось установить свойство: age. Значение должно быть строкой.
proxyUser.age = "25"; // Вывод: Установка свойства: age на значение 25
console.log(proxyUser.age); // Вывод: Доступ к свойству: age \n 25
В этом примере:
Объект Reflect предоставляет способ вызова встроенных операций JavaScript в виде функций. Каждая функция в объекте Reflect соответствует ловушке прокси и имеет то же имя и функциональность. Это позволяет легко использовать поведение по умолчанию при реализации ловушек в прокси.
Пример использования Reflect в прокси
const person = {
firstName: "Алиса",
lastName: "Смит"
};
const handler = {
get(target, prop) {
console.log(`Получение ${prop}`);
return Reflect.get(target, prop);
},
set(target, prop, value) {
console.log(`Установка ${prop} на значение ${value}`);
return Reflect.set(target, prop, value);
}
};
const proxyPerson = new Proxy(person, handler);
console.log(proxyPerson.firstName); // Вывод: Получение firstName \n Алиса
proxyPerson.age = 30; // Вывод: Установка age на значение 30
console.log(proxyPerson.age); // Вывод: Получение age \n 30
В этом примере:
Использование Reflect гарантирует выполнение стандартного поведения, что может быть полезно для:
Можно использовать прокси для проверки значений перед их установкой.
const settings = {
brightness: 50
};
const handler = {
set(target, prop, value) {
if (prop === 'brightness' && (value < 0 || value > 100)) {
throw new Error("Яркость должна быть в пределах от 0 до 100.");
}
return Reflect.set(target, prop, value);
}
};
const proxySettings = new Proxy(settings, handler);
try {
proxySettings.brightness = 120; // Ошибка: Яркость должна быть в пределах от 0 до 100.
} catch (e) {
console.error(e.message);
}
proxySettings.brightness = 80; // Успех
console.log(proxySettings.brightness); // Вывод: 80
В этом примере:
Вы можете использовать динамические импорты вместе с прокси для условной загрузки модулей.
const handler = {
get(target, prop) {
if (prop === 'loadModule') {
return async (moduleName) => {
const module = await import(`./${moduleName}.js`);
return module;
};
}
return Reflect.get(target, prop);
}
};
const moduleLoader = new Proxy({}, handler);
// Динамическая загрузка модуля
moduleLoader.loadModule('utils')
.then(module => {
console.log(module);
})
.catch(err => {
console.error('Не удалось загрузить модуль:', err);
});
В этом примере: