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
