Lesson 26 of 80
A Proxy wraps an object and lets you intercept the fundamental operations on it — get, set, delete — the same operations the prototype chain quietly handles by default.
12 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 2
You create `const logged = new Proxy(user, handler)`. Does mutating `user` directly (not through `logged`) still trigger the proxy's traps?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
Every time you read a property, write one, or check in, the engine performs a fundamental operation on the object — normally handled silently (falling back to the prototype chain if the property isn't found directly). A Proxy lets you intercept those operations with your own function, called a trap.
const user = { name: "Ada" };
const logged = new Proxy(user, {
get(target, prop) {
console.log(`reading ${String(prop)}`);
return Reflect.get(target, prop); // forward to the default behavior
},
set(target, prop, value) {
if (prop === "name" && typeof value !== "string") {
throw new TypeError("name must be a string");
}
return Reflect.set(target, prop, value);
},
});
logged.name; // logs "reading name", returns "Ada"
logged.name = 42; // throws TypeError
Reflect is the companion object with the same set of operations as plain functions (Reflect.get, Reflect.set, ...) — inside a trap, it's the correct way to perform the "default" version of the operation you're intercepting, rather than reimplementing it yourself.
logged.name — the read doesn't go straight to the real object. It passes through the get trap first.
user itself is unchanged; only operations through logged are intercepted. Code that still has a reference to the original user bypasses every trap.Reflect, not by re-implementing the operation. Reflect.set(target, prop, value) correctly handles inheritance and edge cases that a naive target[prop] = value inside the trap can get subtly wrong.has (intercepts the in operator), deleteProperty (intercepts delete), and apply (intercepts calling the object as a function, if it's a function).Proxy comes up less as "write one from scratch" and more as "explain how a reactive framework (Vue, MobX) or a validation library detects property access" — recognizing Proxy+Reflect as the underlying mechanism is the actual signal.