Proxy and the get and set traps
Proxy is a wrapper around an object (or a function) that intercepts operations on it: reading, writing, calling and so on. The proxy sits between the object and the code that uses it, and decides by itself how to react to each operation.
Theory
TL;DR
- Syntax:
new Proxy(target, handler). targetis the original object we want to work with.handleris an object of traps, special interceptor methods that describe how to react to different operations.getintercepts reading a property,setintercepts writing one.- Proxies let you log access, validate data, build reactive objects and hide private fields.
- The
settrap must returntrue, otherwise strict mode throws aTypeError.
Quick example
javascript
const proxy = new Proxy(target, handler);targetis the original object (the one we want to work with);handleris an object of traps, special interceptor methods that describe how to react to different operations.
What proxies are for
Proxies let you step into the basic behaviour of objects, for example:
- log access to properties;
- validate data on write;
- create reactive objects (this is exactly how it works in Vue);
- load values lazily;
- protect private data.
An example, logging every access to an object:
javascript
const user = { name: 'Tim', age: 25 };
const proxy = new Proxy(user, {
get(target, prop) {
console.log(`Reading property "${prop}"`);
return target[prop];
}
});
console.log(proxy.name); // log: Reading property "name"What the get trap does
get(target, prop, receiver) fires when a property of the object is accessed:
javascript
proxy.name;
proxy['age'];It lets you:
- control what is returned on read;
- substitute default values;
- build computed properties;
- hide particular fields.
Example:
javascript
const user = { name: 'Tim' };
const proxy = new Proxy(user, {
get(target, prop) {
if (prop === 'greet') {
return `Hello, ${target.name}!`;
}
return target[prop] ?? 'No such property';
}
});
console.log(proxy.name); // 'Tim'
console.log(proxy.greet); // 'Hello, Tim!'
console.log(proxy.age); // 'No such property'What the set trap does
set(target, prop, value, receiver) fires when we assign a value:
javascript
proxy.age = 30;It lets you:
- validate the new data;
- forbid a write;
- change values automatically;
- trigger side effects (reactivity, logging and so on).
Example:
javascript
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;
console.log(`Property "${prop}" is set to ${value}`);
return true; // you must return true when everything went fine
}
});
proxy.age = 25; // log: Property "age" is set to 25
proxy.name = 'Tim';
proxy.age = 'a lot'; // TypeErrorSummary
| Component | Purpose |
|---|---|
Proxy(target, handler) | Creates a wrapper around an object |
target | The original object |
handler | The object of traps (interceptor methods) |
get | Intercepts reading a property |
set | Intercepts writing a property |
Common mistakes
- Forgetting
return truein thesettrap. In strict mode, and therefore in modules, a failed assignment throws aTypeError. - Thinking the proxy changes the original object. Only operations that go through the proxy are intercepted; direct access to
targetbypasses the traps entirely. - Forgetting that
propcan be a symbol. Aprop === 'age'comparison will never match aSymbolkey, so check the key type when it matters. - Writing
target[prop]instead ofReflect.get(target, prop, receiver). Direct access breaks getters and inheritance, becausethisinside them ends up wrong. - Expecting the
gettrap to behave withJSON.stringifythe way a plain object does. Serialization also goes through the traps, so computed fields can unexpectedly leak into the output. - Reaching for a proxy where a plain getter and setter would do. A proxy is more expensive per operation and makes debugging noticeably harder.
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.