blog

  • Home
  • blog
  • ES6 in Action: How to Use Proxies

ES6 in Action: How to Use Proxies

In computing terms, proxies sit between you and the things you’re communicating with. The term is most often applied to a proxy server — a device between the web browser (Chrome, Firefox, Safari, Edge etc.) and the web server (Apache, Nginx, IIS etc.) where a page is located. The proxy server can modify requests and responses. For example, it can increase efficiency by caching regularly accessed assets and serving them to multiple users.

ES6 proxies sit between your code and an object. A proxy allows you to perform meta-programming operations such as intercepting a call to inspect or change an object’s property.

The following terminology is used in relation to ES6 proxies:

target
The original object the proxy will virtualize. This could be a JavaScript object such as the jQuery library or native objects such as arrays or even another proxies.

handler
An object which implements the proxy’s behavior using…

traps
Functions defined in the handler which provide access to the target when specific properties or methods are called.

It’s best explained with a simple example. We’ll create a target object named target which has three properties:

const target = {
  a: 1,
  b: 2,
  c: 3
};

We’ll now create a handler object which intercepts all get operations. This returns the target’s property when it’s available or 42 otherwise:

const handler = {
  get: function(target, name) {
    return (
      name in target ? target[name] : 42
    );
  }
};

We now create a new Proxy by passing the target and handler objects. Our code can interact with the proxy rather than accessing the target object directly:

const proxy = new Proxy(target, handler);

console.log(proxy.a);  // 1
console.log(proxy.b);  // 2
console.log(proxy.c);  // 3
console.log(proxy.meaningOfLife);  // 42

Let’s expand the proxy handler further so it only permits single-character properties from a to z to be set:

const handler = {
  get: function(target, name) {
    return (name in target ? target[name] : 42);
  },

  set: function(target, prop, value) {
    if (prop.length == 1 && prop >= 'a' && prop <= 'z') {
      target[prop] = value;
      return true;
    }
    else {
      throw new ReferenceError(prop + ' cannot be set');
      return false;
    }
  }
};

const proxy = new Proxy(target, handler);

proxy.a = 10;
proxy.b = 20;
proxy.ABC = 30;
// Exception: ReferenceError: ABC cannot be set

Proxy Trap Types

We’ve seen the get and set in action which are likely to be the most useful traps. However, there are several other trap types you can use to supplement proxy handler code:

  • construct(target, argList)
    Traps the creation of a new object with the new operator.
  • get(target, property)
    Traps Object.get() and must return the property’s value.
  • set(target, property, value)
    Traps Object.set() and must set the property value. Return true if successful. In strict mode, returning false will throw a TypeError exception.
  • deleteProperty(target, property)
    Traps a delete operation on an object’s property. Must return either true or false.
  • apply(target, thisArg, argList)
    Traps object function calls.
  • has(target, property)
    Traps in operators and must return either true or false.
  • ownKeys(target)
    Traps Object.getOwnPropertyNames() and must return an enumerable object.
  • getPrototypeOf(target)
    Traps Object.getPrototypeOf() and must return the prototype’s object or null.
  • setPrototypeOf(target, prototype)
    Traps Object.setPrototypeOf() to set the prototype object. No value is returned.
  • isExtensible(target)
    Traps Object.isExtensible() which determines whether an object can have new properties added. Must return either true or false.
  • preventExtensions(target)
    Traps Object.preventExtensions(), which prevents new properties from being added to an object. Must return either true or false.
  • getOwnPropertyDescriptor(target, property)
    Traps Object.getOwnPropertyDescriptor(), which returns undefined or a property descriptor object with attributes for value, writable, get, set, configurable and enumerable.
  • defineProperty(target, property, descriptor)
    Traps Object.defineProperty() which defines or modifies an object property. Must return true if the target property was successfully defined or false if not.

Continue reading %ES6 in Action: How to Use Proxies%

LEAVE A REPLY