Martyn Ball
Martyn Ball

Reputation: 4885

JavaScript Watch removing watched value from object

i'm trying to watch an objects value, and if it changes, so some stuff..

So this is my object,

var list = [{
   object: undefined,
   index: 0,
   src: 'url here',
   active: { val: 0 }
}]

So I made active an additional object as I create a new object from the above, but make the active value the value from above, this keeps a reference of this object between the 2 objects.

var newList = [];
newList.push({
  object: undefined,
  index: 0,
  src: list[i].src,
  active: list[i].active // Use reference to old list
});

So i'm trying to watch the active value like so:

(list.active).watch('val', function() {
  if (list.active.val === 1) {
    console.log('active');
    list.object.classList.add('active');
  } else {
    console.log('not active');
    list.object.classList.remove('active');
  }
});

However it appears that when I watch this value it is being removed, as if I console.log out the list, then the value is set to undefined! I'm changing the value of list.active.val after adding the watch events.

Here is the Polyfill i'm using for the watch functionality.

// object.watch
if (!Object.prototype.watch) {
  Object.defineProperty(Object.prototype, "watch", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function (prop, handler) {
      var oldval = this[prop],
          newval = oldval,
          getter = function () {
            return newval;
          },
          setter = function (val) {
           oldval = newval;
            return newval = handler.call(this, prop, oldval, val);
          };

      if (delete this[prop]) { // can't watch constants
        Object.defineProperty(this, prop, {
          get: getter,
          set: setter,
          enumerable: true,
          configurable: true
        });
      }
    }
  });
}

// object.unwatch
if (!Object.prototype.unwatch) {
  Object.defineProperty(Object.prototype, "unwatch", {
    enumerable: false,
    configurable: true,
    writable: false,
    value: function (prop) {
      var val = this[prop];
      delete this[prop]; // remove accessors
      this[prop] = val;
    }
  });
}

Edit 1

Added the proxy-observe Polyfill however this doesn't appear to be watching still, I have added it like so:

list[0] = Object.observe(list[0], function(changeset) {
  console.log('changed');
});

list[0].active contains the object { val: 0 }, so it should be observicing this object.

Not getting any errors, it's just doing nothing, ideas?

Upvotes: 0

Views: 294

Answers (1)

Hitmands
Hitmands

Reputation: 14179

You don't need to implement a custom watch/unwatch features, Ecmascript 2015 already provides a specific api:

Proxy

There are a plenty of polyfills to make it working on legacy browsers.

There was a proposal called Object.Observe to address what you need and you can find a Proxy porting here: https://github.com/anywhichway/proxy-observe

Follows a basic working example:

// Your Observable target
const target = Object.create(null);

const observer = {
  set(target, key, value) {
    console.log(`Should we set '${value}' as value of '${key}' property?`)
    
    target[key] = value;
  },
};


const observable = new Proxy(target, observer);
observable.someKindOfProperty = 'Hello World'; 

Upvotes: 1

Related Questions