Skip to content

Instantly share code, notes, and snippets.

@mliezun
Created December 31, 2021 20:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mliezun/5946c8af80e3747519175027579414fb to your computer and use it in GitHub Desktop.
Save mliezun/5946c8af80e3747519175027579414fb to your computer and use it in GitHub Desktop.
Playing with Javascript Proxies (getters/setters)
const validate = (prop, value) => {
// Make sure that the property and value are serializable
// JSON.stringify throws an error if not serializable
const l = {}
l[prop] = value
JSON.stringify(l)
return l
}
const nestedExists = (obj, ks) => {
for (let j = 0; j < ks.length; j++) {
let k = ks[j];
if (!(k in obj)) {
return false
}
obj = obj[k]
}
return true
}
const wrapObject = (parent, key, current) => {
const rootObj = {
parent: Object.freeze(parent),
layers: [Object.freeze({'value': current, 'previous': null})],
pushLayer (l) {
if (parent) {
const ll = {}
ll[key] = l['value']
const previous = parent.getLayer([key])
parent.pushLayer(Object.freeze({'value': ll, previous}))
} else {
this.layers.push(Object.freeze(l))
}
},
getLayer (ks) {
for (let i = this.layers.length - 1; i >= 0; i--) {
let v = nestedExists(this.layers[i]['value'], ks)
if (v) {
return this.layers[i]
}
}
if (parent) {
let ll = parent.getLayer([key].concat(ks))
while (ll) {
let a = nestedExists(ll['value'][key], ks)
if (a) {
return Object.freeze({'value': ll['value'][key]})
}
ll = ll.previous
}
}
},
getValue (k) {
const l = this.getLayer([k])
if (l) {
return Object.freeze(l['value'][k])
}
}
}
const rootProxy = {
get: function(obj, prop) {
validate(prop, null)
const val = rootObj.getValue(prop)
if (typeof val == 'object') {
return wrapObject(rootObj, prop, val).objects
}
return val
},
set: function(obj, prop, value) {
const l = validate(prop, value)
rootObj.pushLayer({'value': l})
}
}
return {
actions: {
revert () {
const pop = rootObj.layers[rootObj.layers.length-1]
rootObj.layers.splice(rootObj.layers.length-1, rootObj.layers.length)
return pop
}
},
objects: new Proxy({}, rootProxy)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment