liveBook · Manning

Proxy

As explained in Secrets of the JavaScript Ninja, Second Edition

A JavaScript object that intercepts operations on a target object using a handler.

A Proxy is an object that routes operations on a target object through handler traps. This lets you add behavior around property access or function calls without weaving that behavior into the target’s own code. section 8.0

Two practical uses show how traps keep extra behavior separate from domain code:

  • Logging property reads and writes: get and set traps report the access while forwarding it to the target. One reusable wrapper can cover multiple properties and objects. section 8.2.1
  • Timing function calls: an apply trap starts a timer, invokes the target, reports elapsed time, and returns the result. Existing function code and call sites need not change. section 8.2.2
Listing 8.9. Using proxies makes it easier to add logging to objects
function makeLoggable(target){                             #A
  return new Proxy(target, {                               #B
    get: (target, property) => {                           #C
      report("Reading " + property);                       #C
      return target[property];                             #C
    },                                                     #C

    set: (target, property, value) => {                       #D
      report("Writing value " + value + " to " + property);   #D
      target[property] = value;                               #D
    }                                                         #D
  });
}

let ninja = { name: "Yoshi"};                              #E
ninja = makeLoggable(ninja);                               #E

assert(ninja.name === "Yoshi", "Our ninja Yoshi");         #F
ninja.weapon = "sword";                                    #F

See a reusable makeLoggable wrapper and how its get and set traps handle property access. section 8.2.1

Listing 8.10. Measuring performance with proxies
function isPrime(number){                             #A
  if(number < 2) { return false; }                    #A
                                                      #A
  for(let i = 2; i < number; i++) {                   #A
     if(number % i === 0) { return false; }           #A
  }                                                   #A
                                                      #A
  return true;                                        #A
}                                                     #A

isPrime = new Proxy(isPrime, {                        #B
  apply: (target, thisArg, args) => {                 #C
    console.time("isPrime");                         #D

    const result = target.apply(thisArg, args);       #E

    console.timeEnd("isPrime");                      #F

    return result;
  }
});

isPrime(1299827);                                     #G

Follow an apply trap that times calls to isPrime while preserving the function’s result. section 8.2.2

How Secrets of the JavaScript Ninja, Second Edition covers it

How deep it goes
Explains get, set, and apply traps through worked examples, without surveying other traps.
Examples
Uses a Ninja object for property logging and an isPrime function for call timing.
What it assumes
Builds on JavaScript objects, property reads and writes, and function calls rather than teaching them from zero.
What you can do after
Apply Proxy traps to log property access and measure function-call duration without modifying target code.
How it connects
Connects proxies with getters and setters, logging, and performance measurement.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Secrets of the JavaScript Ninja, Second Edition. The section links point to the parts of the book it draws on.