As demonstrated in this SO question, Proxy
objects are a good way to watch for changes in an object.
What if you want to watch changes to subobjects? You'd need to proxy those subobjects as well.
I'm currently working with some code that does that automatically - any time you try to set a property it makes sure that it is wrapped in a proxy. We're doing this so that we can perform an action every time any value changes.
function createProxiedObject(objToProxy) {
return new Proxy(objToProxy, {
set: function (target, key, value) {
//proxy nested objects
if (value !== null && typeof value === 'object') {
value = createProxiedObject(value);
}
target[key.toString()] = value;
handleProxiedObjectChange();
});
This works pretty well, but there is at least one case in which this backfires:
function ensureObjectHasProperty(object, key, default) {
if (object[key] !== null) {
// some validation happens here
return object[key];
} else {
return default;
}
}
...
proxiedObject = somethingThatCreatesAProxiedObject(someValue);
proxiedObject[someProperty] = ensureObjectHasProperty(proxiedObject, someProperty, defaultValue)
The result is that the value under someProperty
(which is already being proxied) gets reassigned to the proxied object, causing it to get wrapped in another proxy. This results in the handleProxiedObjectChange
method being called more than once each time any part of the object changes.
The simple way to fix it is to never assign anything to the proxied object unless it's new, but as this problem has already happened there's a reasonable chance someone will do it again in the future. How can I fix the set
function to not rewrap objects that are already being proxied? Or is there a better way to watch an object so that handleProxiedObjectChange
can be called any time the object or any of its subobjects change?