Skip to main content

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).
  • target is the original object we want to work with.
  • handler is an object of traps, special interceptor methods that describe how to react to different operations.
  • get intercepts reading a property, set intercepts writing one.
  • Proxies let you log access, validate data, build reactive objects and hide private fields.
  • The set trap must return true, otherwise strict mode throws a TypeError.

Quick example

javascript
const proxy = new Proxy(target, handler);
  • target is the original object (the one we want to work with);
  • handler is 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'; // TypeError

Summary

ComponentPurpose
Proxy(target, handler)Creates a wrapper around an object
targetThe original object
handlerThe object of traps (interceptor methods)
getIntercepts reading a property
setIntercepts writing a property

Common mistakes

  • Forgetting return true in the set trap. In strict mode, and therefore in modules, a failed assignment throws a TypeError.
  • Thinking the proxy changes the original object. Only operations that go through the proxy are intercepted; direct access to target bypasses the traps entirely.
  • Forgetting that prop can be a symbol. A prop === 'age' comparison will never match a Symbol key, so check the key type when it matters.
  • Writing target[prop] instead of Reflect.get(target, prop, receiver). Direct access breaks getters and inheritance, because this inside them ends up wrong.
  • Expecting the get trap to behave with JSON.stringify the 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 ready
Premium

A concise answer to help you respond confidently on this topic during an interview.