Proxy: target, handler и ловушки

Proxy — обёртка вокруг другого объекта (target). Операции (чтение, запись, in, delete, вызов) сначала попадают в соответствующую функцию handler, то есть в ловушку. Если ловушка не написана, операция идёт прямо в target.

javascript
const p = new Proxy(target, handler);
Proxy: код, ловушка и target
Proxy: код, ловушка и target

Первый аргумент любой ловушки — всегда target. receiver — это сам Proxy (или объект, наследующий от него).

💡 Reflect — стандартные версии тех же операций: внутри ловушки, чтобы сказать «просто выполни как обычно», вызывают Reflect.get, Reflect.set и т. д.


get и set: значения по умолчанию и валидация

get перехватывает каждое чтение. Для отсутствующего ключа вернём текст (prop может быть символом, поэтому String(prop)):

javascript
const defaults = { theme: 'light', lang: 'az' };

const settings = new Proxy(defaults, {
  get(target, prop, receiver) {
    if (prop in target) return Reflect.get(target, prop, receiver);
    return `no setting "${String(prop)}"`;
  },
});

console.log(settings.theme);
console.log(settings.fontSize);

set перехватывает каждое присваивание. На неверном значении бросайте ошибку, на верном возвращайте результат Reflect.set:

javascript
const user = new Proxy({}, {
  set(target, prop, value, receiver) {
    if (prop === 'age' && !Number.isInteger(value)) {
      throw new TypeError('age must be an integer');
    }
    return Reflect.set(target, prop, value, receiver);
  },
});

user.age = 30;
console.log(user.age);
try {
  user.age = 'old';
} catch (e) {
  console.log(`${e.name}: ${e.message}`);
}