What does notifier.performChange actually do?

ecmascript-harmony, javascript, object.observe

Solution

After an hour of doing a lot of testing I finally figured it out. I had the same question (what is `performChange` for?), and also the same idea to just take that off and call

this.a += amount;
this.b += amount;

However: the point of `notifier.performChange` is so that the observer does not observe each change.

I was testing it like this:

var obj = {
  x: 5,
  y: 10
};

function noti() {
  console.log('noti start');
  var notifier = Object.getNotifier(obj);

  notifier.performChange('ok', function() {
    obj.x++;
    obj.y++;
  });

  notifier.notify({
    type: 'ok',
    oldValue: 5
  });
  console.log('noti end');
};

function noti2() {
  console.log('noti2 start');
  var notifier = Object.getNotifier(obj);

  obj.x++;
  obj.y++;

  notifier.notify({
    type: 'ok',
    oldValue: 5
  });
  console.log('noti2 end');
};

function observer(changes) {
  for (var change of changes) {
    console.log('observer: change =', change, ' newValue=', change.object[change.name]);
  }
};

Object.observe(obj, observer, ['ok', 'update']);

console.log('calling noti2()');
noti2(); //will log the changes of update twice becuase of the x and y property of obj

// add delay manually because observer calls are asynchronous and
// we want to clearly separate the notification function calls in our logs
setTimeout(function() {
  console.log('calling noti()');

  noti(); //will only log the ok type. that's what they mean by big change
          //so everything you do inside the performChange won't be observed
}, 100);

It should return the following console output:

calling noti2()
noti2 start
noti2 end
observer: change = Object {type: "update", object: Object, name: "x", oldValue: 5}  newValue= 6
observer: change = Object {type: "update", object: Object, name: "y", oldValue: 10}  newValue= 11
observer: change = Object {object: Object, type: "ok", oldValue: 5}  newValue= undefined

calling noti()
noti start
noti end
observer: change = Object {object: Object, type: "ok", oldValue: 5}  newValue= undefined

Problem

I am trying to understand `Object.getNotifier(object).performChange`. Conceptually I understand that it is designed for defining "macro" or higher level changes. From the example everyone seems to refer to: ``` increment: function(amount) { var notifier = Object.getNotifier(this); notifier.performChange(Thingy.INCREMENT, function() { this.a += amount; this.b += amount; }, this); notifier.notify({ object: this, type: Thingy.INCREMENT, incremented: amount }); } ``` What I do not understand is, how is this different from simply executing the anonymous function passed to `notifier.performChange` directly, instead of as a callback? In other words, how does it differ from the below: ``` increment: function(amount) { var notifier = Object.getNotifier(this); this.a += amount; this.b += amount; notifier.notify({ object: this, type: Thingy.INCREMENT, incremented: amount }); } ``` I have seen that in the latest spec, `notifier.performChange` may return an object, which is then issued as a notification, as in: ``` notifier.performChange(Thing.INCREMENT, function() { this.a += amount; this.b += amount; // a notification is issues with this return value, // including the type passed to notifier.performChange, // and the object underlying notifier. return {incremented: amount}; }); ``` That eliminates the need for the following `notifier.notify` in the original code, but still, is this something other than sugar, or is there a functional difference between this and just making the changes and issuing the notification yourself?

Original source