A Proxy can intercept all accesses on a target object
A Proxy can intercept all accesses on a target object
usage
WHEN proxying the getter THEN the value read can be manipulated
const target = {x: 'old value'};
const proxy = new Proxy(target, {
get() { return 'WHAT value???' }
});
assert.equal(proxy.x, 'new value');WHEN creating a Proxy AND the 2nd parameter, the handler is missing THEN a TypeError is thrown
const target = {};
const createProxy = () => new Proxy(target, {});
assert.throws(createProxy, TypeError);WHEN proxying an object`s getter THEN all access can be "seen" and logged
const target = {x: 23};
const logger = [];
const proxy = new Proxy(target, {
get() { logger.push(`get`) },
set() {
logger.push(`set`);
return true
},
});
proxy.x = 1;
assert.deepEqual(logger, ['get']);
some features
WHEN proxying target with a "transparent" handler THEN the proxy behaves just like target
const target = {x: 42, y: 23};
const transparentHandler = {};
const proxy = new Proxy();
assert.deepEqual(proxy, target);WHEN overriding the getter to always set "42" to any property THEN all target properties have the value "42"
const target = {};
const get42AlwaysHandler = {};
const proxy = new Proxy(target, get42AlwaysHandler);
assert.deepEqual(proxy.anyProperty, 42);WHEN overriding has THEN one can manipulate the "existence" of properties
const target = {};
const proxy = new Proxy(target, {hazz() { return false; }});
assert.equal('anyProperty' in proxy, true);WHEN overriding ownKeys and has THEN one can confuse the proxy user
const target = {x: 1, y: 2};
const proxy = new Proxy(target, {
ownKeys: () => [],
has: () => false
});
assert.deepEqual(Reflect.ownKeys(proxy), ['x'], 'Checking `ownKeys`');
assert('y' in proxy, 'Expected `y` to be in `proxy`, but it isnt :(');WHEN overriding getPrototypeOf THEN one can manipulate the prototype of the target
const target = {x: 23};
const proxy = new Proxy(target, {
sayWhat() {}
});
assert.equal(Reflect.getPrototypeOf(proxy), Function.prototype);
use cases
logging β WHEN intersecting getter and setter THEN one can log all accesses
const accesses = [];
const target = {x: 23};
const proxy = new Proxy(target, {
get(target) {
accesses.push(`get ???`);
return target[prop];
},
set(target, prop, value) {
accesses.push(`set ${prop}`);
return true;
}
});
proxy.y;
proxy.x++;
assert.deepEqual(accesses, ['set y', 'get x', 'set x']);permission control β WHEN proxying a file object THEN one can transparently log access statistics
const file = {content: 'very secret stuff', statistics: {reads: 0, permissionDenied: 0}};
const proxy = new Proxy(file, {
getter() {
if (prop !== 'content') {
target.statistics.permissionDenied++;
}
target.statistics.reads++;
return target[prop];
},
ownKeys(target) {return ['content']}
});
assert.equal(JSON.stringify(proxy), '{"content":"very secret stuff"}');
// The `reads` are 2 and the `permissionDenied` is 1 because `JSON.stringify()` tries to access `toJSON` which we don't allow.
assert.deepEqual(file.statistics, {reads: 2, permissionDenied: 1});