Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Listener for property value changes in a Javascript object

Going through Javascript documentation, I found the following two functions on a Javascript object looks interesting:

.watch - Watches for a property to be assigned a value and runs a function when that occurs.
.unwatch - Removes a watchpoint set with the watch method.


UPDATE: Deprecation warning
Do not use watch() and unwatch()! These two methods were implemented only in Firefox prior to version 58, they're deprecated and removed in Firefox 58+


Sample usage:

o = { p: 1 }; o.watch("p", function (id,oldval,newval) {     console.log("o." + id + " changed from " + oldval + " to " + newval)     return newval; }); 

Whenever we change the property value of "p", this function gets triggered.

o.p = 2;   //logs: "o.p changed from 1 to 2" 

I am working on Javascript for the past few years and never used these functions.
Can someone please throw some good use cases where these functions will come in handy?

like image 314
Naga Kiran Avatar asked Jun 30 '09 13:06

Naga Kiran


People also ask

How do you trigger an event when a variable's value is changed JavaScript?

There is no event which is raised when a given value is changed in Javascript. What you can do is provide a set of functions that wrap the specific values and generate events when they are called to modify the values.

How do you observe a variable in JavaScript?

Seven methods for detecting a change to a javascript variable. The options include polling, monioring an object's variable, monitoring an array element, and using a CSS animation event to trigger modification to the DOM, and finally using MutationObserver to notify modification to the DOM.


1 Answers

It's now 2018 and the answers to this question are a bit outdated:

  • Object.watch and Object.observe are both deprecated and should not be used.
  • onPropertyChange is a DOM element event handler that only works in some versions of IE.
  • Object.defineProperty allows you to make an object property immutable, which would allow you to detect attempted changes, but it would also block any changes.
  • Defining setters and getters works, but it requires a lot of setup code and it does not work well when you need to delete or create new properties.

Today, you can now use the Proxy object to monitor (and intercept) changes made to an object. It is purpose built for what the OP is trying to do. Here's a basic example:

var targetObj = {}; var targetProxy = new Proxy(targetObj, {   set: function (target, key, value) {       console.log(`${key} set to ${value}`);       target[key] = value;       return true;   } });  targetProxy.hello_world = "test"; // console: 'hello_world set to test' 

The only drawbacks of the Proxy object are:

  1. The Proxy object is not available in older browsers (such as IE11) and the polyfill cannot fully replicate Proxy functionality.
  2. Proxy objects do not always behave as expected with special objects (e.g., Date) -- the Proxy object is best paired with plain Objects or Arrays.

If you need to observe changes made to a nested object, then you need to use a specialized library such as Observable Slim (which I authored). It works like this:

var test = {testing:{}}; var p = ObservableSlim.create(test, true, function(changes) {     console.log(JSON.stringify(changes)); });  p.testing.blah = 42; // console:  [{"type":"add","target":{"blah":42},"property":"blah","newValue":42,"currentPath":"testing.blah",jsonPointer:"/testing/blah","proxy":{"blah":42}}] 
like image 78
Elliot B. Avatar answered Sep 21 '22 03:09

Elliot B.