Object.observe -- not supported by all major browsers, what can I use as an alternative?
Asked Answered
L

1

13

I have this function that works in Chrome, which prints to the console when a variable called finishedLoading changes values.

Object.observe(finishedLoading, function(id, oldval, newval) {
         console.log('finished loading' + id + ' went from ' + oldval + ' to ' + newval);
     }

This doesn't work in a bunch of other modern browsers (e.g. firefox, safari). Is there an alternative I can use that would be better supported? Thanks!

Lohse answered 22/2, 2015 at 18:13 Comment(5)
Use a callback or promise?Procurable
Have a look at polyfills.ioInduce
Wow, polyfills.io is great. Just added that one line and everything works beautifully. Thanks!Lohse
Object.observe is dead, the spec will never make it to the spec and v8 will eventually remove it. Sorry.Limestone
A simple method would be to use getter and setter, where you add your notification there when a value is changed.Quartz
A
12

A more widely supported approach could be Object.defineProperty. defineProperty can be used to have some control on a certain property of an object for instance:

var o = { prop: '' };
Object.defineProperty(o, 'prop', {
  get: function() { return this.value; },
  set: function(newValue) {
    // a certain property is being changed
    alert('is changed');
    this.value = newValue; 
  }
});

o.prop = 'Johnson';

The above example shows how you can use defineProperty and when prop of object o is altered a defined setter (set) is called.

At the bottom of this reference you can see that even IE-8 supports it but only under certain conditions (IE8 only support Object.defineProperty to be used on DOM nodes).

But be careful when using it because this would assign a property to the window object as well because of a missing this:

var o = { b:''};
Object.defineProperty(o, 'b', {
  get: function() { return value; },
  set: function(newValue) { value = newValue; },
});

o.b = 'abc';
console.log(window.value); // 'abc'

Way to track old value of a property

This matches more your request:

var o = { prop: '' };

Object.defineProperty(o, 'prop', {
  get: function() { return this.propValue; },
  set: function(newValue) {
    // an certain property is being changed
    console.log('old-value: ',this['oldprop']);
    console.log('new-value: ',newValue);
    this.propValue = newValue; 
    this['oldprop'] = this.propValue;
  }
});

o['prop'] = 'joseph';
console.log(o);
o['prop'] = 'jack';
console.log(o);
o['prop'] = 'john';
console.log(o);

Observe whole Object by using Object.defineProperty

And in addition to that you could make a function that tracks a whole object and whether any property is being changed:

function observeObject(obj){

  var keys = Object.keys(obj);

  for(var k=0; k < keys.length; k++){

    var key = keys[k];

    (function(key){

      var keyName = key+'value';
      var oldKeyName = 'old'+key+'value';

      obj[oldKeyName] = obj[key];

      Object.defineProperty(obj, key, {
        get: function() { return this[keyName]; },
        set: function(newValue) {

          console.log('old-value: ',this[oldKeyName]);
          console.log('new-value: ',newValue);

          this[keyName] = newValue; 
          this[oldKeyName] = this[keyName];

        }
      });



    })(key);

  }

}


var person = { name : 'jack', age: 26 };

observeObject(person);

person.name = 'john';
person['age'] = 27;
Ables answered 22/2, 2015 at 18:27 Comment(1)
you can see that even IE-8 supports it but under certain conditions. IE8 only support Object.defineProperty to be used on DOM nodes.Gonfalon

© 2022 - 2024 — McMap. All rights reserved.