Skip to content
  • Proxy & Reflect · JavaScript

Proxy & Reflect

LearnViaNotes @learnvianotes· 2 min read

A Proxy wraps an object and intercepts fundamental operations — get, set, delete, in, function calls. Reflect provides the default behaviour for each trap.

Traps

TrapIntercepts
get(target, prop, receiver)obj.prop, obj[prop]
set(target, prop, value, receiver)obj.prop = value
has(target, prop)prop in obj
deleteProperty(target, prop)delete obj.prop
ownKeys(target)Object.keys, for…in, Reflect.ownKeys
apply(target, thisArg, args)Calling a function proxy
construct(target, args)new on a proxy

Validation and defaults

JavaScript
const user = new Proxy({}, {
  set(target, prop, value, receiver) {
    if (prop === "age" && (!Number.isInteger(value) || value < 0)) {
      throw new TypeError(`age must be a non-negative integer, got ${value}`);
    }
    return Reflect.set(target, prop, value, receiver);   // default behaviour
  },
  get(target, prop, receiver) {
    return prop in target ? Reflect.get(target, prop, receiver) : `<no ${String(prop)}>`;
  },
});
user.name = "Asha";
user.age = 30;
try { user.age = -5; } catch (e) { console.log(e.message); }
console.log(user.name, user.age, user.email);
Output
age must be a non-negative integer, got -5
Asha 30 <no email>

Observing changes (how Vue 3 reactivity works)

JavaScript
function reactive(obj, onChange) {
  return new Proxy(obj, {
    set(target, prop, value) {
      const old = target[prop];
      const ok = Reflect.set(target, prop, value);
      if (old !== value) onChange(prop, old, value);
      return ok;
    },
  });
}
const state = reactive({ count: 0 }, (k, a, b) => console.log(`${k}: ${a} → ${b}`));
state.count++;
state.count += 5;
state.count = 6;          // unchanged → no notification
Output
count: 0 → 1
count: 1 → 6

Negative array indices, and hiding private keys

JavaScript
const arr = new Proxy([10, 20, 30], {
  get(target, prop, receiver) {
    const i = Number(prop);
    return Number.isInteger(i) && i < 0 ? target[target.length + i] : Reflect.get(target, prop, receiver);
  },
});
console.log(arr[-1], arr[0], arr.length);

const hidden = new Proxy({ id: 1, _secret: "x" }, {
  has: (t, p) => !String(p).startsWith("_") && p in t,
  ownKeys: (t) => Reflect.ownKeys(t).filter((k) => !String(k).startsWith("_")),
});
console.log("_secret" in hidden, Object.keys(hidden));
Output
30 10 3
false [ 'id' ]

Reflect

JavaScript
const obj = { a: 1 };
console.log(Reflect.has(obj, "a"), Reflect.ownKeys(obj), Reflect.get(obj, "a"));
console.log(Reflect.defineProperty(Object.freeze({}), "x", { value: 1 }));   // false, no throw
console.log(Reflect.apply(Math.max, null, [1, 5, 3]));
Output
true [ 'a' ] 1
false
5

What are real-world uses of Proxy?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report