I have recently been digging into proxy in Javascript. I was surprised by what it can do. Proxy allows you to hook into fundamental operations of the language constructs (like object, arrays, functions..)
Here is list of simple usecases for javascript proxy
Freezing Object
We can prevent mutation of objects easily with few lines of code essentially freezing the object
const hero = {
name: 'Saitama',
age: 25,
class: 'B',
race: 'Human',
heroName: 'Caped Baldy',
};
const Freeze = obj =>
new Proxy(obj, {
set: function(target, key, value) {
throw Error("You can't change values this object has been frozen");
},
});
const saitama = Freeze(hero);
saitama.name = 'Garuro'; // This will throw error
You can also freeze arrays, Map, WeakMap, Set...
Tracking changes on object
Proxy can be used track changes to object essentially maintain history.
const createHistory = obj => {
let history = [JSON.parse(JSON.stringify(obj))];
const proxiedObject = new Proxy(obj, {
set: function(target, key, value) {
history.push({ ...target, [key]: value });
Reflect.set(target, key, value);
},
});
return [history, proxiedObject];
};
const [history, proxiedObject] = createHistory(hero);
proxiedObject.name = 'Genos';
proxiedObject.class = 'C';
console.log(history);
history object will contains snapshot of changes made to the object
[
{
name: 'Saitama',
age: 25,
class: 'B',
race: 'Human',
heroName: 'Caped Baldy'
},
{
name: 'Genos',
age: 25,
class: 'B',
race: 'Human',
heroName: 'Caped Baldy'
},
{
name: 'Genos',
age: 25,
class: 'C',
race: 'Human',
heroName: 'Caped Baldy'
}
]
similarly you can also track number of times function was called with apply trigger.
Case insensitive key access
const caseInsensitive = obj =>
new Proxy(obj, {
get: function(target, key) {
// I am assuming keys are lowercase by default for simplicity
return Reflect.get(target, key.toLowerCase());
},
});
const proxiedObject = caseInsensitive(hero);
console.log(proxiedObject.name); // saitama
console.log(proxiedObject.NAME); // saitama
Handling properties that does not exist
You can easily handle undefined properties by following snippet
const FetchValue = obj =>
new Proxy(obj, {
get: function(target, key) {
if (target.hasOwnProperty(key)) {
return [Reflect.get(target, key), true];
}
return [null, false];
},
});
const proxiedObject = FetchValue(hero);
const [name, nameExist] = proxiedObject.name;
const [city, cityExist] = proxiedObject.city;
if (nameExist) {
console.log(name);
}
if (cityExist) {
console.log(city); // this is not executed since property city does not exist
}
You can do much more with proxy than what is listed here. You can look up more awesome usage here https://github.com/mikaelbr/awesome-es2015-proxy
Top comments (0)