Watching object property changes with Proxy in JavaScript

I was doing yet another tracking code integration but this time something managed to catch my eye. In order to track the current page / context in Single Page Apps, all you had to do was update the string property of a pre-defined JavaScript object and that was it. No callbacks, no function calls or anything of the sort.

Tracking any changes to that property was automatically done by their library, or so they bragged. This got me curious since I never had the opportunity to create such a feature. So I did what every reasonable developer would do: dig around to see how it works.

The gist of it is using a Proxy object. If the MDN documentation looks be a bit confusing, since a Proxy can do so much more, try this JavaScript Proxy tutorial, it was much more clear for me.

If you are simply looking for a useful code snippet, no non-sense, you can use the sample below.

var tracking_object = {
    context: 'Homepage'
};

const handler = {
    set: function (target, property, value) {
        if (property === 'context') {
            if (typeof value !== 'string') {
                throw new Error('Context must be a string, not ', typeof value);
            }

            console.log('The property was set, we can announce the server!');
        }
        target[property] = value;
    }
};

tracking_object = new Proxy(tracking_object, handler);

Here's how it works: we start with a JavaScript object with a property that we want to watch, tracking_object in this case, with the context key.

var tracking_object = {
    context: 'Homepage'
};

Next we define a handler. The structure is important, it needs a set method that will be called every time tracking_object changes.
The params are pretty straightforward: target is the object itself, property is the string value of the property and value is the value being set.

If the property is the one we want, "context", we do what must be done. In my case, I added an extra type validation, so the user will only be able to set strings as values, and a console.log placeholder method.

const handler = {
    set: function (target, property, value) {
        if (property === 'context') {
            if (typeof value !== 'string') {
                throw new Error('Context must be a string, not ', typeof value);
            }

            console.log('The property was set, we can announce the server!');
        }
        target[property] = value;
    }
};

Finally, we replace the object with a Proxy.

tracking_object = new Proxy(tracking_object, handler);

If, for example, you will attempt to set the context to a number, an error will be thrown and the property will remain unchanged. And if you do a simple value attribution, tracking_object.context = 'Blog';, the watcher will kick in, as seen in the screenshot below.

A suprinsingly simple integration but with very powerful results and infinite opportunities! And if you somehow need the reverse, to have a property or an object that cannot be changed, please refer to my older post: Making an unmodifiable object in Javascript