Safe, exception-free access to object properties in Javascript using Proxy objects.
const safe = require('safeproxy');
const obj = safe({
family: {
wife: 'whitney',
kids: [ 'june', 'charlie' ]
}
});
// normal access
console.log(obj.family.wife); // prints "whitney"
console.log(obj.family.kids); // prints "[ 'june', 'charlie' ]"
console.log(obj.family.kids[0]); // prints "june"
// unsafe access made safe
console.log(obj.what.is.going.on.here); // prints "{}"
console.log(obj.can[3].even[123][432].handle.arrays[9]); // prints "{}"
console.log(obj.family.kids[2].my.parents.want.another.grandkid); // prints "{}"
// even works with functions
console.log(obj.i.cant().believe[1][2][3].this.doesnt().throw); // prints "{}"
A specialized Javascript Proxy object is used to override all property access (get
) on the "safe" object. If the safe object encounters a property access for which it has no value, instead of returning undefined
, it instead returns an empty Proxy object, allowing chained property access to safely continue. It works for object and array access, and even works for function calls.
Be aware that "safe" objects will make use of these property access trap handlers throughout their entire structure. There is minimal overhead imposed on objects utilizing these traps, so take that into account when using them.
Safe object access, particularly in testing, can be really useful and save a lot of ugly validation code.
let obj = JSON.parse(someMassiveStringOrNetworkResponse()),
data;
// without safe access
data = obj && obj.foo && obj.foo.bar && obj.foo.bar.quux && obj.foo.bar.quux.lukasavage;
// or you could try
try {
data = obj.foo.bar.quux.lukasavage;
} catch (e) {
// handle exception
}
// or keep it clean with safe access
const safe = require('safeproxy');
data = safe(obj).foo.bar.quux.lukasavage;
And why did I write a module when others exist? I wanted safe access with the ability to have safe access on objects, arrays, and functions but NOT have:
?
existential operators (like Coffeescript)- underscore dependency (like safe-obj)
- object wrapped in a string (like safe-object, safe-get, deep-access, or undefsafe)
- weird
__value
unwrapper (like safeproxy) - pattern-matching semantics (like safe-object-proxy)
- For node.js usage, version 6.0 or higher is required.
- For browser usage, check Can I Use? for Proxy support. As of the writing of these docs, all major browsers are supporting it (minus IE11).
- Gidi Meir Morris's article on this topic is where I found this pattern. Big thanks to him for taking the time to share and break it down.
- Tom Van Cutsem's post that explained how to stringify Proxy objects.