Q36 of 40 · JavaScript
What is the `Reflect` API, and how does it complement `Proxy`?
Short answer
Short answer: `Reflect` provides static methods mirroring Proxy traps, allowing clean forwarding to the target's default behaviour inside trap handlers. Without `Reflect`, forwarding requires `target[prop]` which can miss receiver-binding and descriptor edge cases. `Reflect` methods also return success flags instead of throwing on failure.
Detail
Reflect is a built-in object (not a constructor) introduced alongside Proxy in ES6. Its methods correspond exactly to Proxy trap names and provide the default behaviour for each operation.
Why it exists: Inside a Proxy trap, you often want to call through to the original behaviour with correct semantics. Using target[prop] directly can break:
- Receiver binding: For accessor properties with getters,
target[prop]calls the getter withthis = target, butReflect.get(target, prop, receiver)passes the Proxy asthis, which is often what inherited getters need. - Success signalling:
Reflect.set()returnstrue/falseinstead of throwing on non-writable properties, making error handling insettraps cleaner.
Reflect methods: Reflect.get, Reflect.set, Reflect.has, Reflect.deleteProperty, Reflect.apply, Reflect.construct, Reflect.ownKeys, and more — one for each Proxy trap.
Testing use: Reflect is used in advanced mock frameworks and assertion libraries to intercept and verify operations. Reflect.apply provides a safe way to call a function with a dynamic argument list, similar to Function.prototype.apply but without needing a method reference.
// EXAMPLE
// Without Reflect — receiver issue
const handler1 = {
get(target, prop) {
return target[prop]; // wrong: 'this' in getter = target, not proxy
}
};
// With Reflect — correct receiver
const handler2 = {
get(target, prop, receiver) {
console.log(`get: ${prop}`);
return Reflect.get(target, prop, receiver); // correct
},
set(target, prop, value, receiver) {
console.log(`set: ${prop} = ${value}`);
return Reflect.set(target, prop, value, receiver); // returns bool
}
};
const proxy = new Proxy({ x: 1 }, handler2);
proxy.x; // logs "get: x" → 1
proxy.y = 2; // logs "set: y = 2"
// Reflect.apply — like Function.prototype.apply but safer
function sum(...args) { return args.reduce((a, b) => a + b, 0); }
Reflect.apply(sum, null, [1, 2, 3]); // 6