Прокси в JavaScript применяются во многих случаях. Рассмотрим три примера, начиная с простых и переходя к более сложным.
Добавление значений по умолчанию
Функция defaultValues оборачивает входящий объект в прокси, добавляя значения по умолчанию для отсутствующих свойств.
const defaultValues = (target, defaultValue = 0) => {
return new Proxy(target, {
get: (obj, prop) => obj.hasOwnProperty(prop) ? obj[prop] : defaultValue
});
};
Функция принимает целевой объект (target) и необязательное значение по умолчанию (defaultValue, по умолчанию 0). Она возвращает прокси, реализующий только метод get. Если свойство существует в объекте, возвращается его значение; иначе – значение по умолчанию.
Пример использования:
const position = defaultValues({ x: 24, y: 42 }, 0);
console.log(position); // {x: 24, y: 42}
console.log(position.z); // 0
console.log(position.someProperty); // 0
Объект position содержит координаты x и y. Обращение к несуществующим свойствам z или someProperty возвращает 0 (значение по умолчанию).
Скрытие свойств объекта
Функция hiddenProps скрывает свойства объекта, начинающиеся с указанного префикса.
const hiddenProps = (target, prefix = '_') => {
return new Proxy(target, {
has: (obj, prop) => obj.hasOwnProperty(prop) && !prop.startsWith(prefix),
ownKeys: (obj) => Reflect.ownKeys(obj).filter(prop => !prop.startsWith(prefix)),
get: (obj, prop) => obj.hasOwnProperty(prop) && !prop.startsWith(prefix) ? obj[prop] : undefined
});
};
Функция принимает целевой объект (target) и необязательный префикс скрываемых свойств (prefix, по умолчанию ‘_’). Прокси реализует методы has, ownKeys и get. Метод has проверяет существование свойства и наличие префикса. ownKeys возвращает массив ключей без свойств с префиксом. Метод get возвращает значение свойства, если оно существует и не начинается с префикса; иначе возвращает undefined.
Пример использования:
const data = hiddenProps({ name: 'Владилен', age: 25, _id: 123 });
console.log(data); // {name: 'Владилен', age: 25}
console.log(data.name); // Владилен
console.log(data.age); // 25
console.log(data._id); // undefined
console.log(data.hasOwnProperty('_id')); // true
Свойства name и age доступны, а свойство _id — скрыто, хотя hasOwnProperty(‘_id’) возвращает true, показывая, что свойство существует в объекте.
Оптимизация поиска элементов в массиве
Класс IndexedArray оптимизирует поиск элементов в массиве по ID с помощью индексации.
class IndexedArray {
constructor(arr) {
this.index = {};
arr.forEach(item => this.index[item.id] = item);
return new Proxy(arr, {
get: (array, prop) => {
switch (prop) {
case 'push':
return (...args) => {
const result = array[prop].call(array, ...args);
args.forEach(item => this.index[item.id] = item);
return result;
};
case 'findByID':
return (id) => this.index[id];
default:
return array[prop];
}
}
});
}
}
const userData = [
{ id: 1, name: 'User1', job: 'Job1', age: 30 },
{ id: 2, name: 'User2', job: 'Job2', age: 25 },
{ id: 3, name: 'User3', job: 'Job3', age: 35 }
];
const users = new IndexedArray(userData);
console.log(users.findByID(2)); // { id: 2, name: 'User2', job: 'Job2', age: 25 }
users.push({id: 4, name: 'User4', job: 'Job4', age: 40});
console.log(users.findByID(4)); // { id: 4, name: 'User4', job: 'Job4', age: 40 }
Класс использует прокси для переопределения метода push и добавления метода findByID. Метод push добавляет элементы в массив и обновляет индекс. Метод findByID осуществляет быстрый поиск по ID, используя индекс.
Эти примеры демонстрируют гибкость и возможности прокси для расширения функциональности объектов и оптимизации работы с данными. Прокси позволяют создавать эффективные решения для различных задач в JavaScript.