What are Proxy traps and what operations can they intercept?
Assesses fundamental understanding of JavaScript conventions, runtime behavior, and memory/performance considerations.
Hiring managers look for precision, avoidance of ambiguous jargon, and ability to explain trade-offs under real production conditions.
Proxy traps are handler methods that intercept fundamental operations on objects, allowing you to customize their behavior.
Available traps:
const handler = {
// Property access
get(target, prop, receiver) {
console.log(`Getting ${prop}`);
return Reflect.get(target, prop, receiver);
},
// Property assignment
set(target, prop, value, receiver) {
console.log(`Setting ${prop} to ${value}`);
return Reflect.set(target, prop, value, receiver);
},
// Property deletion
deleteProperty(target, prop) {
console.log(`Deleting ${prop}`);
return Reflect.deleteProperty(target, prop);
},
// 'in' operator
has(target, prop) {
console.log(`Checking ${prop}`);
return Reflect.has(target, prop);
},
// Object.keys, for...in
ownKeys(target) {
return Reflect.ownKeys(target);
},
// Function calls
apply(target, thisArg, args) {
console.log(`Called with ${args}`);
return Reflect.apply(target, thisArg, args);
},
// new operator
construct(target, args) {
console.log(`Constructed with ${args}`);
return Reflect.construct(target, args);
},
// Object.getPrototypeOf
getPrototypeOf(target) {
return Reflect.getPrototypeOf(target);
},
// Object.setPrototypeOf
setPrototypeOf(target, proto) {
return Reflect.setPrototypeOf(target, proto);
},
// Object.isExtensible
isExtensible(target) {
return Reflect.isExtensible(target);
},
// Object.preventExtensions
preventExtensions(target) {
return Reflect.preventExtensions(target);
},
// Object.getOwnPropertyDescriptor
getOwnPropertyDescriptor(target, prop) {
return Reflect.getOwnPropertyDescriptor(target, prop);
},
// Object.defineProperty
defineProperty(target, prop, descriptor) {
return Reflect.defineProperty(target, prop, descriptor);
}
};
Validation example:
const validator = {
set(target, prop, value) {
if (prop === 'age') {
if (typeof value !== 'number' || value < 0) {
throw new TypeError('Age must be a positive number');
}
}
target[prop] = value;
return true;
}
};
const person = new Proxy({}, validator);
person.age = 30; // OK
// person.age = -5; // Throws error
Property access logging:
function createLoggingProxy(obj, name = 'object') {
return new Proxy(obj, {
get(target, prop) {
console.log(`${name}.${String(prop)} accessed`);
const value = target[prop];
if (typeof value === 'object' && value !== null) {
return createLoggingProxy(value, `${name}.${String(prop)}`);
}
return value;
}
});
}
const user = createLoggingProxy({ name: 'John', address: { city: 'NYC' } });
user.address.city; // Logs: object.address accessed, object.address.city accessed
Negative array indices:
function createArray(arr) {
return new Proxy(arr, {
get(target, prop) {
const index = Number(prop);
if (index < 0) {
return target[target.length + index];
}
return target[prop];
}
});
}
const arr = createArray([1, 2, 3, 4, 5]);
console.log(arr[-1]); // 5
console.log(arr[-2]); // 4
Function argument validation:
function validateArgs(fn, validators) {
return new Proxy(fn, {
apply(target, thisArg, args) {
validators.forEach((validator, i) => {
if (!validator(args[i])) {
throw new Error(`Invalid argument at position ${i}`);
}
});
return Reflect.apply(target, thisArg, args);
}
});
}
const add = validateArgs(
(a, b) => a + b,
[
x => typeof x === 'number',
x => typeof x === 'number'
]
);
console.log(add(1, 2)); // 3
// add('1', 2); // Throws error
Candidate Response Strategy & Interview Tips
- Start with a concise one-sentence summary: Deliver a direct, confident answer first before expanding into nuances.
- Demonstrate real-world trade-offs: Discuss where this approach excels and when you would avoid it in production systems.
- Discuss complexity & edge cases: Proactively explain time/space complexity or boundary conditions (null values, scale limits).
- Prepare for interviewer follow-ups: Technical hiring panels frequently probe deeper into concurrency, backward compatibility, or alternative libraries.