Watch for Object Changes with JavaScript
Watching for changes to an object's property has always been a much sought after task; many shims have been used over the years to listen to object changes. These days we have better methods for listening to object changes: the Proxy API. Sindre Sorhus has created on-change, a tiny JavaScript tool that allows you to listen for changes on JavaScript objects and arrays!
on-change JavaScript
Since the on-change code is so tiny, here it is in its full glory:
'use strict'; module.exports = (object, onChange) => { const handler = { get(target, property, receiver) { try { return new Proxy(target[property], handler); } catch (err) { return Reflect.get(target, property, receiver); } }, defineProperty(target, property, descriptor) { onChange(); return Reflect.defineProperty(target, property, descriptor); }, deleteProperty(target, property) { onChange(); return Reflect.deleteProperty(target, property); } }; return new Proxy(object, handler); };
The onChange
function returns a proxy which you'll use to make any object changes.
Using on-change
Pass onChange
the object you'd like to spy on and a change handler function:
let j = { a: 1 }; // Upon change, save to server let changeable = onChange(j, () => save(j));
Then use that Proxy to change properties and get notified of changes:
// Make a change that would trigger changes changeable.a = 2; // save() is triggered! // j.a === 2
Note that the original object's values also change -- that's the beauty of Proxy! Also note that on-change doesn't tell you which property changed; the use case, as Sindre describes, is saving an object (to server, etc.) when any part of an object changes. You could also use ti for a small library with a render function, re-rendering the content whenever a property changed!
This on-change library is really nice if you don't need to know which property changed, just that something changed.
If someone wonders what this
Reflect
object it. I stumbled across on-change a few days ago and wrote about it. :)https://www.stefanjudis.com/today-i-learned/the-global-reflect-object-its-use-cases-and-things-to-watch-out-for/
Just a note that watching an object really bogs down all accesses to the object. It’s great for debugging but don’t build a lot of functionality around it in your production code.
It is worth mentioning that arrays are not handled by this function and push/pop/delete to an array needs to be handled by overwriting those methods.
Thanks for this David, I’m relatively novice to programming (used mostly in webobjects within Storyline) so forgive me if my question seems idiotic. I checked out Proxy Api and it’s browser compatibility excludes IE. Is there an alternative to onChange for IE?
Nice solution,
But to create a proxy for change notification purposes is not the same that observe changes on an object. In your solution, you create a different object – the proxy – to operate with and force the developer to abandon the use of the original object. The best explanation is an example:
Why this detail is, sometimes, important. Because, sometimes, you are not the owner of the object
j
and the owner does not want to change thej
reference for your proxy. Imagine a situation where you are a framework developer and want to observe changes in some code of your user by maintaining transparency from her perspective.If you want another example I can detail the corner case that brought me here. In my case, my
j
object is a DOM element and I cannot replace it with a proxy.