Proxy wraps an object and intercepts operations. Reflect provides methods that correspond to proxy traps — used as the default behavior inside handlers.

Basic Proxy

  let target = { name: 'Alice', age: 25 };

let handler = {
    get(obj, prop) {
        console.log(`Getting ${prop}`);
        return Reflect.get(obj, prop);
    },
    set(obj, prop, value) {
        console.log(`Setting ${prop} to ${value}`);
        return Reflect.set(obj, prop, value);
    }
};

let proxy = new Proxy(target, handler);
proxy.name;      // logs "Getting name"
proxy.age = 26;  // logs "Setting age to 26"
  

Validation Proxy

  function createValidatedUser(data) {
    return new Proxy(data, {
        set(obj, prop, value) {
            if (prop === 'age' && (typeof value !== 'number' || value < 0)) {
                throw new TypeError('Age must be a non-negative number');
            }
            return Reflect.set(obj, prop, value);
        }
    });
}

let user = createValidatedUser({ name: 'Bob', age: 30 });
user.age = 31;   // OK
// user.age = -1; // TypeError
  

Default Values

  let withDefaults = new Proxy({}, {
    get(obj, prop) {
        if (prop in obj) return obj[prop];
        return `(default: ${prop})`;
    }
});

console.log(withDefaults.foo); // '(default: foo)'
  

Negative Array Indices

  let arr = new Proxy([1, 2, 3], {
    get(target, prop) {
        let index = Number(prop);
        if (index < 0) {
            index = target.length + index;
        }
        return target[index];
    }
});

console.log(arr[-1]); // 3
  

Revocable Proxy

  let { proxy, revoke } = Proxy.revocable({ secret: 42 }, {});
console.log(proxy.secret); // 42
revoke();
// proxy.secret; // TypeError: Cannot perform 'get' on proxy that has been revoked
  

Reflect Methods

Method Operation
Reflect.get Read property
Reflect.set Write property
Reflect.has in operator
Reflect.deleteProperty delete
Reflect.apply Function call
Reflect.construct new
  function greet(name) {
    return `Hello, ${name}`;
}

Reflect.apply(greet, null, ['Alice']); // 'Hello, Alice'
  

Reactive Data (Vue 3 Concept)

Frameworks use Proxy for reactivity:

  function reactive(obj, onChange) {
    return new Proxy(obj, {
        set(target, prop, value) {
            const old = target[prop];
            const result = Reflect.set(target, prop, value);
            if (old !== value) onChange(prop, value);
            return result;
        }
    });
}

let state = reactive({ count: 0 }, (prop, val) => {
    console.log(`${prop} changed to ${val}`);
});
state.count = 1; // logs change
  

When to Use Proxy

  • Validation and access control
  • Logging and debugging
  • Virtual objects (API wrappers)
  • Reactive state systems

Avoid Proxy for simple cases — it adds overhead and can complicate debugging.