What does the Proxy object do?
Proxy is one of the most powerful and "magical" tools in JavaScript.
It lets you intercept and redefine the behavior of objects -
that is, stand "between" an object and its usage.
What Proxy is:
Proxy is a wrapper around an object
that lets you intercept operations on it: reading, writing, deleting properties, calling functions, and so on.
You can "redefine" the behavior of an object - how it reacts to obj.prop, obj[key], delete obj.x, in obj and much more.
Syntax:
const proxy = new Proxy(target, handler);| Argument | Description |
|---|---|
target | the original object being wrapped |
handler | an object with "traps" (interceptor functions) |
The simplest example:
const user = { name: "Alice", age: 25 };
const proxy = new Proxy(user, {
get(target, prop) {
console.log(`Accessing property "${prop}"`);
return target[prop];
}
});
console.log(proxy.name); // Accessing property "name" -> AliceEvery time proxy.name happens,
the call goes through the trap get(),
not directly into the object.
Main "traps":
| Trap | Intercepts | Example |
|---|---|---|
get(target, prop) | reading a property | proxy.x |
set(target, prop, value) | writing a property | proxy.x = 10 |
has(target, prop) | the in operator | "x" in proxy |
deleteProperty(target, prop) | delete proxy.x | |
ownKeys(target) | Object.keys(proxy) | |
apply(target, thisArg, args) | calling a function | proxy() |
construct(target, args) | calling via new | new proxy() |
Example: logging changes
const user = { name: "Alice" };
const proxy = new Proxy(user, {
set(target, prop, value) {
console.log(`Changed ${prop}: ${target[prop]} -> ${value}`);
target[prop] = value;
return true; // must return true
}
});
proxy.name = "Bob"; // Changed name: Alice -> BobNow you can "catch" every change in the object.
Example: protecting against property deletion
const obj = { secret: 42 };
const proxy = new Proxy(obj, {
deleteProperty(target, prop) {
console.log(`Deletion forbidden: ${prop}`);
return false;
}
});
delete proxy.secret; // "Deletion forbidden: secret"Example: data validation
const user = {};
const proxy = new Proxy(user, {
set(target, prop, value) {
if (prop === "age" && typeof value !== "number") {
throw new TypeError("Age must be a number");
}
target[prop] = value;
return true;
}
});
proxy.age = 30; // OK
proxy.age = "thirty"; // TypeErrorYou can attach "rules" to writing properties - a great technique for data validation.
Example: default value
const data = { a: 1 };
const proxy = new Proxy(data, {
get(target, prop) {
return prop in target ? target[prop] : "No data";
}
});
console.log(proxy.a); // 1
console.log(proxy.b); // "No data"Now accessing a nonexistent property does not return undefined,
but returns a nice default value instead.
Example: observer (reactive data, like in Vue.js)
function reactive(obj) {
return new Proxy(obj, {
set(target, prop, value) {
console.log(`Updated ${prop}: ${value}`);
target[prop] = value;
return true;
}
});
}
const state = reactive({ count: 0 });
state.count++; // "Updated count: 1"This is exactly how reactive data is implemented in frameworks (Vue, MobX, and others).
Example: intercepting a function call
function sum(a, b) {
return a + b;
}
const proxy = new Proxy(sum, {
apply(target, thisArg, args) {
console.log(`Called with arguments: ${args}`);
return target(...args) * 2; // changing the result!
}
});
console.log(proxy(2, 3)); // Called with arguments: 2,3 -> 10You can wrap even functions, changing their behavior "on the fly".
Why you need Proxy:
Logging and debugging Data validation Reactive objects (for example, Vue.js) Lazy-loading Safe "readonly" structures Building APIs with "magic" properties
In short:
| Property | Proxy |
|---|---|
| What it does | Intercepts operations on an object |
| Works with | Objects and functions |
| Used for | logging, validation, reactivity |
| Changes the original? | No, wraps it |
| Example traps | get, set, apply, deleteProperty, construct |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.