Marcell CD

The Proxy Pattern in JavaScript

The Proxy pattern is like having a helpful assistant that stands between you and an object. This assistant controls how you can access and interact with that object.

Think of it like a receptionist at a company. When you want to talk to someone, you go through the receptionist first. They might check if the person is available, take a message, or direct you to the right place. That’s exactly what a proxy does with objects!

How Does It Work?

The proxy sits between the client (that’s you or your code) and the main object. When you want to do something with the object, your request goes through the proxy first. The proxy can then decide what to do - maybe it adds some extra functionality, validates your request, or simply passes it along.

The cool thing is that you don’t even know you’re talking to a proxy. It looks and acts just like the original object.

Why Would You Want to Use a Proxy?

Here are some common reasons:

A Simple Example

Let’s say you have a dog object and you want to control how people interact with it:

const snickers = {
  name: "Snickers",
  age: 2,
  breed: "King Charles",
  owner: "Marcell Ciszek",
}

const handler = {
  get(target, prop) {
    console.log(`Someone is asking for ${prop}`)
    return Reflect.get(target, prop)
  },
  set(target, prop, value) {
    console.log(`Someone is setting ${prop} to ${value}`)
    return Reflect.set(target, prop, value)
  },
}

const dogProxy = new Proxy(snickers, handler)

// Now when you use dogProxy, it will log every access
console.log(dogProxy.name) // Logs: "Someone is asking for name" then "Snickers"
dogProxy.age = 3 // Logs: "Someone is setting age to 3"

JavaScript makes this easy with the built-in Proxy object and Reflect methods. The Reflect object provides clean methods for getting and setting properties that work perfectly with proxies.

Creating Read-Only Enums

Here’s a practical example - creating enums that can’t be changed:

const createEnum = (values) => {
  return new Proxy(values, {
    get(target, key) {
      if (!target.hasOwnProperty(key)) {
        throw new Error(`"${key}" doesn't exist in this enum`)
      }
      return target[key]
    },
    set() {
      throw new Error("You can't change enum values!")
    },
  })
}

const Days = createEnum({
  Monday: 1,
  Tuesday: 2,
  Wednesday: 3,
  Thursday: 4,
  Friday: 5,
})

console.log(Days.Monday) // Works fine: 1
// Days.Monday = 10; // This would throw an error
// Days.Saturday; // This would also throw an error

This creates a safe enum that prevents accidental changes and catches typos.

The Good and Not-So-Good

The Good:

The Not-So-Good:

Wrapping Up

The Proxy pattern is like having a smart assistant for your objects. It lets you add extra functionality, control access, and keep your original objects safe - all without changing how you use them.

It’s particularly useful when you need to:

The JavaScript Proxy API makes this pattern easy to implement and very powerful to use.