While browsing through some programming books, I came across Understanding ECMAScript 6 which had a cool section on Proxies.
Proxies are objects which we can use to intercept operations on target objects. Below, we define a Proxy for an empty object where we override the setter.

const target = {};
const proxy = new Proxy(target, {
  set: (obj, prop, value) => {
    console.log(`Setting ${prop} to ${value}`)
    obj[prop] = value;
  }
});

Now when we set a value on our proxy, our target will have that value and our log will be called:

proxy.name = 'turtle'
'Setting name to turtle'

Proxies are built using the Reflect API and can be used for validating getters/setters. The example below shows how we can throw an error if a property does not exist on the target.

const target = {
  name: 'hi',
};
const proxy = new Proxy(target, {
  get: (target, prop, receiver) => {
    if (prop in receiver) {
      return Reflect.get(target, prop, receiver);
    }
    throw new Error('property does not exist!');
  }
});

proxy.name // 'hi'
proxy.dne // Uncaught Error: property does not exist!

Some use cases for proxies:

  • Validation: Is the input a valid integer?
  • Caching: Can we return the data from memory instead of fetching from our api?
  • Observability: Can we be notified when an object's state is changed?

Go out there and build!