Categories
Modern JavaScript

Best of Modern JavaScript — Proxies

Spread the love

Since 2015, JavaScript has improved immensely.

It’s much more pleasant to use it now than ever.

In this article, we’ll look at metaprogramming with JavaScript proxies.

Metaprogramming

Metaprogramming is writing code that processes our app-level code.

App-level code is code that takes user input and returns output for the user.

There’re various kinds of metaprogramming.

One kind is introspection. This is where we have read-only access to the structure of a program.

Self-modification is where we change the program’s structure.

Intercession is where we redefine the semantics of some language operation.

An example of introspection in Javascript is using Object.keys() to get the keys of the object.

An example of self-modification is to move a property from one place to another.

For instance, we can write:

function moveProperty(source, prop, target) {
  target[prop] = source[prop];
  delete source[prop];
}

to move the prop property from the source object to the target object.

Then we delete the source object’s prop property.

Proxies let us do intercession with our JavaScript app.

We can change how object operations are done with it.

Proxies

Proxies bring intercession to JavaScript.

We can do many operations with an object.

We can get the property value, and we can set it.

Also, we can check if property is in an object.

We can customize these operations with proxies.

For example, we can write:

const target = {};
const handler = {
  get(target, propKey, receiver) {
    console.log(target, propKey, receiver);
    return 'foo';
  }
};
const proxy = new Proxy(target, handler);

console.log(proxy.bar)

We create an empty target object that we use with the proxy.

And the handler object has a get method that lets us return a value for the properties given.

target is the object we passed into the first argument of the Proxy constructor.

propKey is the property name.

So if we get the value of proxy.bar or any other property of proxy , we get 'foo' returned.

We can also change the way that we check if a property exists in an object.

For example, we can write:

const target = {};
const handler = {
  has(target, propKey) {
    console.log(propKey);
    return true;
  }
};
const proxy = new Proxy(target, handler);

console.log('bar' in proxy);
console.log('foo' in proxy);

Then we get the target and propKey parameters, which hold the same values as the ones in get .

We returned true so whenever we use the in operator with it, it returns true .

The set method can let us change how objects are set.

Intercepting Method Calls

We can intercept method calls by calling the methods in object properties our way.

For instance, we can write:

const target = {
  foo(text) {
    return `text ${text}`;
  }
};

const handler = {
  get(target, propKey, receiver) {
    const origMethod = target[propKey];
    return function(...args) {
      const result = origMethod.apply(this, args);
      console.log(JSON.stringify(args), JSON.stringify(result));
      return result;
    };
  }
};
const proxy = new Proxy(target, handler);

console.log(proxy.foo('baz'));

We call the target.foo method within th get method of the handler .

Inside the get method, we call the method with the arguments but with this being the proxy instead of the target object.

This way, we can change the behavior of the method call.

We logged the arguments and the results of it.

It’s handy for logging method calls.

Conclusion

Proxies let us run control how object properties are get and set.

We can also change the way that properties are check.

Leave a Reply

Your email address will not be published.

If you like the content of this blog, subscribe to my email list to get exclusive articles not available to anyone else.