Proxy & Reflect
Intercept the fundamental operations on an object -- reads, writes, has, delete -- and forward them cleanly.
new Proxy(target, { get, set, has });
Reflect.get(target, key, receiver)A Proxy wraps a target object and lets you intercept its basic operations via traps: get, set, has, deleteProperty, apply, and more. It is metaprogramming: you customise what property access itself means.
const safe = new Proxy(target, {
get(obj, key) {
if (!(key in obj)) throw new Error(`no such key: ${String(key)}`);
return obj[key];
},
});Reflect is the matching toolkit
Reflect exposes those same internal operations as plain functions -- Reflect.get, Reflect.set, Reflect.has. Inside a trap you call the corresponding Reflect method to perform the default behaviour correctly, including proper this and return values.
Real uses
Reactive frameworks (Vue 3), validation layers, negative array indexing, default-value objects, access logging, and API mocks are all built on proxies.
Example
When to use it
- Log every property access on a configuration object using a get trap to debug unexpected reads.
- Validate that only numbers are set on a numeric data store using a set trap that throws on invalid input.
- Build a reactive data model where any property change automatically triggers a UI re-render callback.
More examples
Proxy get trap for logging
The get trap intercepts every property read, logs it, and forwards the call to the real object with Reflect.get.
const obj = { name: "Alice", age: 30 };
const proxy = new Proxy(obj, {
get(target, key) {
console.log("Read:", key);
return Reflect.get(target, key);
}
});
console.log(proxy.name); // logs "Read: name" then "Alice"Proxy set trap for validation
The set trap validates that every assigned value is a number before forwarding it with Reflect.set.
const nums = new Proxy({}, {
set(target, key, value) {
if (typeof value !== "number") throw new TypeError("Numbers only");
return Reflect.set(target, key, value);
}
});
nums.x = 42; // ok
// nums.y = "hi"; // TypeError: Numbers onlyReactive proxy triggers callback
Wraps a data object in a Proxy that calls an onChange callback whenever any property is updated.
function reactive(data, onChange) {
return new Proxy(data, {
set(target, key, value) {
const result = Reflect.set(target, key, value);
onChange(key, value);
return result;
}
});
}
const state = reactive({ count: 0 }, (k, v) => console.log(`${k} changed to ${v}`));
state.count = 1; // "count changed to 1"
Discussion