CodeBlanks Logo Icon CodeBlanks

Default behavior with Reflect

JavaScript course · Expert · Lesson 38/63

Learn to apply default behavior inside a trap and manage side effects with Reflect.

Default behavior with Reflect

When writing a trap, you often want to do something first and then apply the normal behavior after. Instead of rewriting the default behavior by hand, you can delegate it to the Reflect API.

Reflect.get(target, prop), Reflect.set(target, prop, value) and friends are mirror images of the Proxy traps. So inside a trap, return Reflect.set(...) runs the default behavior as if no trap existed.

This is the safe way to extend behavior: you do not duplicate the default and stay correct across engine changes.

Reflect.apply and Reflect.construct

Reflect is not only for property reads and writes. It also covers function calls and constructions.

Reflect.apply(fn, thisArg, args) calls a function with a specific this and argument list; like Function.prototype.apply but clearer. Reflect.construct(Constructor, args) matches new Constructor(...args).

These are especially useful inside apply and construct traps: you can add logging, counting or rate limiting before the real call happens.

Exercise Write a logging Proxy

Define a user object with a name: 'Alex' property. Inside a handler, write a set(target, prop, value, receiver) trap: log with console.log('set', prop), then return Reflect.set(target, prop, value, receiver). Create proxy = new Proxy(user, handler). Assign proxy.age = 28 and log it with console.log(proxy.age).

Show example solution
const user = { name: 'Alex' };
const handler = {
  set(target, prop, value, receiver) {
    console.log('set', prop);
    return Reflect.set(target, prop, value, receiver);
  }
};
const proxy = new Proxy(user, handler);
proxy.age = 28;
console.log(proxy.age);

Test yourself

  1. Why use Reflect.set inside a set trap?

    • Because it is faster
    • To safely reapply the default behavior
    • To turn off debugging
    • To freeze the Proxy
    Show answer

    To safely reapply the default behavior — Correct! Reflect.set applies the default behavior briefly and correctly, including invariants.

  2. Apply the default behavior

    const handler = {
      set(target, prop, value, receiver) {
        console.log('set', prop);
        return ____;
      }
    };
    Show answer
    const handler = {
      set(target, prop, value, receiver) {
        console.log('set', prop);
        return Reflect.set(target, prop, value, receiver);
      }
    };
  3. Match each Reflect method to its operation

    Reflect.get
    Read property
    Reflect.set
    Assign property
    Reflect.has
    in operator
    Reflect.apply
    Call function
    Reflect.construct
    Build with new

All lessons in Expert