Difficulty: Advanced
What are the Proxy and Reflect APIs in JavaScript? How do they enable meta-programming?
Proxy wraps an object and intercepts operations (get, set, delete, etc.) via handler functions called traps. It allows you to customize fundamental object behaviors.
Reflect provides methods that mirror the Proxy traps, making it easy to call the default behavior from within a trap without losing context.
Common uses: validation on property assignment, reactive data systems (Vue 3's reactivity), access logging, default value proxies, and deep object observation.
const validator = {
set(target, key, value) {
if (key === 'age' && typeof value !== 'number') {
throw new TypeError('age must be a number');
}
if (key === 'age' && value < 0) {
throw new RangeError('age must be non-negative');
}
return Reflect.set(target, key, value);
}
};
const person = new Proxy({}, validator);
person.name = 'Alice';
person.age = 30;
console.log(person.age); // 30
try {
person.age = -5;
} catch (e) {
console.log(e.message); // age must be non-negative
}
The set trap intercepts every property assignment. Reflect.set() calls the default assignment behavior.
function createLoggingProxy(target) {
return new Proxy(target, {
get(obj, key) {
console.log(`Getting: ${String(key)}`);
return Reflect.get(obj, key);
},
set(obj, key, value) {
console.log(`Setting: ${String(key)} = ${value}`);
return Reflect.set(obj, key, value);
}
});
}
const user = createLoggingProxy({ name: 'Bob' });
user.name;
user.role = 'admin';
const withDefaults = (obj, defaultVal) =>
new Proxy(obj, {
get: (target, key) =>
key in target ? target[key] : defaultVal
});
const config = withDefaults({ timeout: 5000 }, 'N/A');
console.log(config.timeout); // 5000
console.log(config.missing); // N/A
Proxies can transparently add logging or default value behavior without modifying the original object.
Proxy, Reflect, Traps, Meta-programming