When Proxy takes control #2
A
Patrick Ness.manJavaScript Object without a filter, is chaos walking
After writing about JavaScript Proxy, this time a short comparison between the object validation in JavaScript: class VS Proxy.
Let say we want to have control over object named Person. To keep it simple, let’s have five rules to demonstrate some consepts:
- Hiding the ID
- Prevent adding new attributes.
- Allowing only aging, and not getting younger.
- Keeping track overall changes.
- Preventing user from changing tracked data
var p = new Person("Me :-)");
p.id == null;
p.name = "You :-\"; //
p._track.pop();// {attr: "name", status: true, value: "You :-\"}
p.age = 18;
p.age = 16; // Age will stay 18
p._track.pop();// {attr: "age", status: false, value: 16}
p.newValue = "Haha"; // Untracked, unwanted value
p._track.pop();// {attr: "newValue", status: false, value: "Haha"}
p._track = []; // Will not change the data
p._track.push({}); // Will not change the data
p._track.pop(); // Will not change the data
We can do most if it by using JavaScript Class
class PersonByClass { constructor(name) { this._id = Math.random() this._track = []; this._name = name; Object.seal(this); } get id(){ return null; } set id(value){ this._track.push({attr:'name',status:true,value,time:new Date()}); return null; } get name(){ return this._name; } set name(value){ this._name = value; this._track.push({attr:'name',status:true,value,time:new Date()}); } get age() { return this._age; } set age(value){ let status = true; if(value < this._age){ console.log('You cant get yonger'); status = false; }else{ this._age = value; } this._track.push({attr:'age',status,value,time:new Date()}); return true; } }
But still, JavaScript as JavaScript you can bypass the validations:
p._id != null;
p.age = 16;
p._age = 6;
p._track = [];
If you want to seal the object from all wanted changes, you want something that will mask everything in the object. This is where the Proxy come in:
class PersonByProxy {
constructor(constructorName) {
let o = {
_track:[],
_validAttr: ['age','name'],
id: Math.random(),
name:constructorName,
ageValidator: (target,value) => !target.age || value >= target.age
}
return new Proxy(o, {
set: function(target, property, value, receiver) {
let status = true;
if(!target._validAttr.find(x => x == property)){
status = false;
console.log('Invalid property');
}
if(target[property+'Validator'] && !target[property+'Validator'](target,value)){
status = false;
console.log('Failed passing the ' + property + 'validation');
}else{
target[property] = value;
}
target._track.push({attr:property,status,value,time:new Date()});
},
get: function(target, property, value, receiver) {
if(property == "_track"){
return target._track.map(x => x);
}
if(!target._validAttr.find(x => x == property)){
console.log('Invalid property');
return false;
}
return target[property];
}
});
}
}
Now you can't add properties, you cant get the ID, You cant pass the validation or change the track. Feels free and open as in North Korea :-\