Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tracking object changes

Tags:

javascript

Like to get some feedback/thoughts about the following challenge.

I have been working on a two way binding library reaching completion and left with an enhancement and looking for the best approach moving forward.

I am tracking the properties of an object (e.g. state) with basic getters/setters. On changes routines are executed to update the DOM. Extremely simplified example:

var state = {propertyA:1,propertyB:2,propertyC:3}
state.forEach((prop) => {
    Object.defineProperty(state, prop, {
        set: function (newValue) {
            value = newValue;
            // routines to update the DOM based on the changed state
        },
        get: function () {
            return value;
        },
        enumerable: true,
        configurable: true
    });
}

However runtime this state object might end up receiving new properties. I seek to remove the dependency of having to manually reinitialize all properties again.

So I need to track the state object and add the necessary setters/getters for the appended properties. I tried the following, but I am not allowed to touch the state object despite having set configurable to true.

Object.defineProperty(window, 'state', {
    set: function (newValue) {
        value = newValue;
        // routine to apply setters/getters for the new properties
    },
    get: function () {
        return value;
    },
    enumerable: true,
    configurable: true
});

I really would like to avoid super nasty stuff like setInterval to check object changes. Any advice on how to handle this situation?

like image 329
Micha Schopman Avatar asked Oct 23 '25 15:10

Micha Schopman


1 Answers

You can use a Proxyobject to do this simply.

For the MDN docs:

The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).

let state = {
  propertyA: 1,
  propertyB: 2,
  propertyC: 3
}

function wrapObject(state) {
  const handler = {
    get: function(obj, prop) {
      console.log("get invoked for prop:: ", prop);
      return prop;
    },
    set: function(obj, prop, value) {
      console.log("set invoked for prop:: ", prop, " and value:: ", value);
      document.getElementById("root").innerHTML = `<div> prop: ${prop} value: ${value} </div>`;
      //Other code
    }
  };
  return new Proxy(state, handler);
}

state = wrapObject(state);
state.propertyA;
state.propertyD = 4;
//Update state by adding new property after 3 secs
setTimeout(() => {
  state.propertyE = 5;
}, 3000);
<div id="root"></div>
like image 99
Fullstack Guy Avatar answered Oct 25 '25 09:10

Fullstack Guy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!