Skip to Content
Course content

243: The Reflect Object

Click on the "Edit" button in the top corner of the screen to edit your slide content.

If you've spent any time with Proxy objects, you know they're incredibly powerful for intercepting operations. But there's a common point of confusion: why do we need the Reflect object? Why can't we just manipulate the target object directly inside our traps?

I used to think Reflect was just "syntactic sugar"—a fancy way of doing things we already knew how to do. I was wrong. Reflect provides a set of methods that mirror the internal operations of JavaScript. When you're inside a Proxy trap, using Reflect ensures that the default behavior of the language is preserved, especially when dealing with inheritance or complex getters and setters.

Building a guarded configuration object

Let's build a configuration manager. I want an object where I can track every time a setting is changed, and I want to prevent certain "frozen" settings from being deleted. Instead of writing a bunch of wrapper functions, we'll use a Proxy.

const appConfig = {
  theme: 'dark',
  apiEndpoint: 'https://api.example.com',
  version: '1.0.0'
};

const handler = {
  get(target, prop, receiver) {
    console.log(`Reading ${prop}...`);
    return Reflect.get(target, prop, receiver);
  },
  deleteProperty(target, prop) {
    if (prop === 'version') {
      console.warn('The version property is protected!');
      return false;
    }
    return Reflect.deleteProperty(target, prop);
  }
};

const config = new Proxy(appConfig, handler);


Notice that I used Reflect.get and Reflect.deleteProperty. In the deleteProperty trap, Reflect.deleteProperty is particularly clean because it returns a boolean indicating whether the operation succeeded, which is exactly what the Proxy trap expects.

The mistake: Ignoring the receiver

Here is where I usually tripped up when I first started using Proxies. Let's add a set trap. At first, I might have written it like this:

// My initial mistake
set(target, prop, value) {
  console.log(`Setting ${prop} to ${value}`);
  target[prop] = value; // Direct assignment
  return true;
}


This looks fine, right? For a simple object, it is. But if our appConfig inherited from another object that had a setter, target[prop] = value would bypass the Proxy's receiver. This means the this context inside that setter would be the original target object, not our Proxy. That's a recipe for subtle, nightmare-inducing bugs in larger applications.

To fix this, I'll use Reflect.set, which takes that third receiver argument:

set(target, prop, value, receiver) {
  console.log(`Updating ${prop} to ${value}`);
  
  // Using Reflect ensures the 'this' context remains the Proxy (receiver)
  return Reflect.set(target, prop, value, receiver);
}


Why this matters in the real world

By using Reflect.set(target, prop, value, receiver), we aren't just assigning a value; we're telling JavaScript, "Perform the default 'set' operation, but make sure you do it as if the Proxy was the object being acted upon."

If you're just building a quick prototype, direct assignment is tempting. But as an engineer, you want your utilities to be robust. Reflect turns the "magic" of Proxies into a predictable, standard API. It separates the interception (the Proxy) from the execution (Reflect).




📋 Practical Task

Implementing a Read-Only API Key Guard

You are building a security wrapper for a credentials object. Your goal is to create a Proxy that allows any property to be read or modified, except for the apiKey property, which should be read-only.

Requirements:

  • Create an object called credentials with at least two properties: username and apiKey.
  • Implement a Proxy handler with a set trap.
  • Inside the set trap, if the property being changed is 'apiKey', log "Error: apiKey is read-only" and return false.
  • For all other properties, use Reflect.set to update the value, ensuring you pass the receiver argument.
  • Test your implementation by attempting to change both the username and the apiKey.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.