Proxy & Reflect
В одной фразе: Proxy перехватывает фундаментальные операции объекта через ловушки (get, set, has, deleteProperty и др.); Reflect — зеркальный API для тех же операций, нужный для корректного forwarding с сохранением receiver и инвариантов. На собесе важно объяснить зачем именно нужен Reflect, а не просто target[prop].
// Validation proxy: проверяем данные на уровне объектаfunction createValidated(schema) { return new Proxy({}, { set(target, prop, value, receiver) { if (prop in schema && !schema[prop](value)) { throw new TypeError(`Invalid ${prop}: ${value}`); } // Reflect.set: учитывает receiver, возвращает boolean return Reflect.set(target, prop, value, receiver); // не просто target[prop] = value — Reflect правильнее }, get(target, prop, receiver) { return Reflect.get(target, prop, receiver); } });}const user = createValidated({ age: v => Number.isInteger(v) && v >= 0 });user.age = 25; // OK// user.age = -1; // TypeError: Invalid age: -1// Reflect: возвращает boolean вместо броска, единый APIconst target = { x: 1 };
// Object.defineProperty бросает TypeError при неудаче// Reflect.defineProperty возвращает false — удобнее в условияхconst ok = Reflect.defineProperty(target, 'y', { value: 2, writable: false });console.log(ok); // true
// Reflect.ownKeys — все ключи: string + symbol + non-enumerableconst sym = Symbol('s');const obj = { a: 1, [sym]: 2 };Object.defineProperty(obj, 'b', { value: 3, enumerable: false });Reflect.ownKeys(obj); // ['a', 'b', Symbol(s)]// Proxy непрозрачен для ===const target = {};const proxy = new Proxy(target, {});proxy === target; // false — разные объекты!
// Ловушки имеют инварианты: нельзя нарушить non-configurable свойстваconst obj2 = Object.defineProperty({}, 'x', { value: 1, configurable: false, writable: false });const p = new Proxy(obj2, { get() { return 99; } // ← попытка нарушить инвариант});// p.x → TypeError: proxy must report the same value// (движок защищает non-configurable non-writable свойства)Итог: Proxy + Reflect — основа реактивных систем (Vue 3), валидации и логирования. Reflect обеспечивает корректный forward с сохранением receiver и инвариантов.