Is there a way to monitor changes to an object?


Instead triggering an event based on user action can you just listen for changes to an object and react then?

Well, depending on the domain you're working with, you can use backbone.js - it has a "model" object that you can extend and connect up to callbacks that get triggered by events automatically when the model is changed - that is, you set a field on the model, and it will automatically fire an event that you can listen to. You have to define your models to extend its Model, and call a setter function instead of setting properties directly, but it's very useful, I recommend it.

Just for clarity's sake, the event is fired from the model on change, so it's fired even if you set the value of the attribute programmatically or in the console.


I've written something like this.

https://github.com/jmoyers/mettle

person.on('name.change', function(val){
    // 'a new name was committed: Yolanda'
    console.log('a new name was committed: ', val)
});

person.name = 'Yolanda';

https://github.com/jmoyers/mettle/blob/master/src/model.coffee

It might be a little much to dig through all the source. Here's an explanation:

The key for my project is two concepts. One is to keep the track a set of attributes and create getters and settes for each using defineGetter and defineSetter. The second is to 'subclass' EventEmitter and broadcast events based on these property changes in your setter.

Track shows how I set up getter/setter for a set of keys.

  Model.prototype.track = function(keys) {
    _.each(keys, __bind(function(key) {
      this.tracked.push(key);
      this.__defineGetter__(key, __bind(function() {
        return this.get(key);
      }, this));
      return this.__defineSetter__(key, __bind(function(val) {
        return this.set(key, val);
      }, this));
    }, this));
    return this;
  };

Here's an example of how to broadcast based on a 'magic' setter:

  Model.prototype.set = function(key, val) {
    this.attribs[key] = val;
    this.emit('change', this.attribs);
    type = key + '.change';
    this.emit(type, val);
  };

This is a simplified example, since I introduced 'attribute middleware' into the mix, but this shows how you could emit a change event based on a property change.


You can use getters and setters ro react on properties change. John Resig have written great article about them.