I ran into an issue with my side project AoS Reminders recently where I was mutating an object that wasn’t supposed to be mutated.
I was having trouble tracking down the mutation, until I stumbled upon the Proxy
object, a helpful tool for any Javascript developer.
const obj = { key1: 'value', key2: 'value2' }
const handler = {
get(target, key) {
console.log('Reading value from ' + key)
return target[key]
},
}
const proxiedObj = new Proxy(obj, handler)
// When we run this `if` statement, console will log
// 'Reading value from key1'
if (proxiedObj.key1) { }
This can be useful for detecting when your objects are being accessed.
Another great example of using Proxy
is for object validation:
// Use the proxy handler as a validator
const validator = {
set: (obj, prop, value) => {
// Validate that we passed in a correct `type` value
if (prop === 'type') {
const validTypes = ['Mage', 'Barbarian', 'Archer']
if (value === null) {
throw new TypeError('Cannot set to type to null');
}
if (!validTypes.includes(value)) {
throw new TypeError('Cannot set to type to ' + value);
}
}
// Store the new value in your object
obj[prop] = value;
// `set` expects a boolean response if successful
return true;
}
};
let char = new Proxy({age: 40, stars: 5}, validator);
char.name = 'Dennis' // Other keys are not validated
char.type = 'Golden God' // Throws `Cannot set to type to Golden God`
console.log(char.type) // undefined
char.type = 'Mage' // Passes validation
console.log(char.type) // 'Mage'
char.type = null; // Throws `Cannot set to type to null`
console.log(char.type) // 'Mage'
While useful, you should really be using Typescript and enforcing your object keys that way ;)
Hope this helps someone! Just thought I’d share a small, neat feature of JS I hadn’t used before.