What does notifier.performChange actually do?

I'm trying to understand Object.getNotifier(object).performChange. Conceptually, I understand that it is designed to detect changes “macro” or higher. From the example, everyone seems to reference :

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
  });
}

I don’t understand how this differs from simply executing an anonymous function passed directly to notifier.performChange, rather than as a callback? In other words, how does it differ from the following:

increment: function(amount) {
  var notifier = Object.getNotifier(this);

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

  notifier.notify({
    object: this,
    type: Thingy.INCREMENT,
    incremented: amount
  });
}

I saw that in the last specification it notifier.performChangecan 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};  
});

notifier.notify , - , , ?

+4
2

, , , , . ( performChange ?),

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

: notifier.performChange , .

:

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 what they mean by big change
          //so everything you do inside the performChange won't be observed
}, 100);

:

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
+4

, , Object.observe spec.

, Object.getNotifier(obj).performChange(changeType, changeFn):

  • changeFn
  • changeFn, , obj
  • changeFn : obj

, %NotifierPrototype%.performChange(changeType, changeFn) - , .

, , -:

1:

increment: function(amount) {
    var notifier = Object.getNotifier(this);

    notifier.performChange(Thingy.INCREMENT, function() {
        this.a += amount;
        this.b += amount;
    });

    notifier.notify({
        object: this,
        type: Thingy.INCREMENT,
        incremented: amount
    });
}

:

  • performChange() .
  • undefined, performChange() -
  • notify()

2:

increment: function(amount) {
    var notifier = Object.getNotifier(this);

    notifier.performChange(Thingy.INCREMENT, function() {
        this.a += amount;
        this.b += amount;

        return { incremented: amount };  
    });
}

:

  • performChange() .
  • , performChange() , , , notify() 1: { object: Object, type: Thingy.INCREMENT, increment: amount }

, performChange(), . , .


. , , increment() , increment() - .

, :

  • performChange()
  • performChange()
  • notify()

, increment() .

increment() ( = , increment(), ), : Object.deliverChangeRecords(callback).

, callback , .

, :

(function() {
    var obj = { prop: "a" };

    Object.observe(obj, function(changes) {
        console.log(changes);
    });
    
    obj.prop = "b";

    Object.deliverChangeRecords(function(changes) {
        console.log(changes);
    });

    console.log("End of execution");
})(); // Meh, we're notified of changes here, which isn't what we wanted
Hide result

:

(function() {
    var obj = { prop: "a" },

        callback = function(changes) {
            console.log(changes);
        };
    
    Object.observe(obj, callback)

    obj.prop = "b";

    Object.deliverChangeRecords(callback); // Notified of changes here, synchronously: yay!

    console.log("End of execution");
})();
Hide result

, Object.observe(obj, callback) obj callback obj ( [[ChangeObservers]] ). ( Object.observe()) , . ( , , type , Object.observe() , - .)

, . , .

Object.deliverChangeRecords(callback): callback , .

, deliverChangeRecords() - . , deliverChangeRecords() , . , deliverChangeRecords().

(function() {
    var obj1 = { prop1: "a" },
        obj2 = { prop2: "a" },

        commonCallback = function(changes) {
            console.log(changes);
        };
    
    Object.observe(obj1, commonCallback);
    Object.observe(obj2, commonCallback);

    obj1.prop1 = "b";
    obj2.prop2 = "b";

    Object.deliverChangeRecords(commonCallback); // Notified of the changes to both obj1.prop1 and obj2.prop2
})();
Hide result

, .

+5

All Articles