October 16

Proxy в Javascript: Что за зверь. Use cases (сценарии использования)

В JavaScript Proxy — это объект, который перехватывает операции с другим объектом, известным как целевой объект (target). Это мощный инструмент для добавления поведения или проверки доступа к объектам.

Ниже приведены несколько примеров использования (use cases) Proxy:

Валидация данных

Proxy можно использовать для проверки данных перед их установкой в объект.

const user = {
  name: 'John',
  age: 25
};

const proxyUser = new Proxy(user, {
  set(target, property, value) {
    if (property === 'age' && typeof value !== 'number') {
      throw new Error('Age must be a number');
    }
    target[property] = value;
    return true;
  }
});

proxyUser.age = 30;  // Всё нормально
proxyUser.age = 'thirty';  // Ошибка: Age must be a number

Логирование операций

Proxy можно использовать для ведения журнала всех действий, происходящих с объектом.

const product = {
  name: 'Laptop',
  price: 1000
};

const proxyProduct = new Proxy(product, {
  get(target, property) {
    console.log(`Accessed property: ${property}`);
    return target[property];
  },
  set(target, property, value) {
    console.log(`Set property ${property} to ${value}`);
    target[property] = value;
    return true;
  }
});

console.log(proxyProduct.name);  // Логирует доступ к свойству "name"
proxyProduct.price = 1200;  // Логирует изменение свойства "price"

Ограничение доступа

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

const secretData = {
  username: 'admin',
  password: '1234'
};

const proxySecretData = new Proxy(secretData, {
  get(target, property) {
    if (property === 'password') {
      throw new Error('Access to password is denied');
    }
    return target[property];
  }
});

console.log(proxySecretData.username);  // 'admin'
console.log(proxySecretData.password);  // Ошибка: Access to password is denied

Автоматическое создание свойств

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

const data = {};

const proxyData = new Proxy(data, {
  get(target, property) {
    if (!(property in target)) {
      target[property] = 0;  // Если свойства нет, создать его с начальным значением 0
    }
    return target[property];
  }
});

console.log(proxyData.counter);  // Выведет 0, даже если свойства "counter" не было
proxyData.counter += 1;
console.log(proxyData.counter);  // Выведет 1

Наблюдение за изменениями

Proxy можно использовать для отслеживания изменений в объекте.

const user = {
  name: 'Alice',
  age: 30
};

const handler = {
  set(target, property, value) {
    console.log(`Property ${property} was changed from ${target[property]} to ${value}`);
    target[property] = value;
    return true;
  }
};

const proxyUser = new Proxy(user, handler);

proxyUser.name = 'Bob';  // Логирует изменение имени с 'Alice' на 'Bob'
proxyUser.age = 35;      // Логирует изменение возраста с 30 на 35

Псевдомассив с отрицательными индексами

Proxy может расширить функциональность массивов, добавив поддержку отрицательных индексов.

const array = [1, 2, 3, 4, 5];

const proxyArray = new Proxy(array, {
  get(target, property) {
    const index = Number(property);
    if (index < 0) {
      return target[target.length + index];
    }
    return target[property];
  }
});

console.log(proxyArray[-1]);  // 5 (последний элемент массива)
console.log(proxyArray[-2]);  // 4

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

А как вы используете Proxy?