Javascript notifier.performChange实际上做什么?

Javascript notifier.performChange实际上做什么?,javascript,ecmascript-harmony,object.observe,Javascript,Ecmascript Harmony,Object.observe,我试图理解对象.getNotifier(对象).performChange。从概念上讲,我理解它是为定义“宏”或更高级别的更改而设计的。从: 我不明白的是,这与直接执行传递给notifier.performChange的匿名函数(而不是作为回调)有何不同?换句话说,它与以下内容有何区别: increment: function(amount) { var notifier = Object.getNotifier(this); this.a += amount; this.b +=

我试图理解
对象.getNotifier(对象).performChange
。从概念上讲,我理解它是为定义“宏”或更高级别的更改而设计的。从:

我不明白的是,这与直接执行传递给
notifier.performChange
的匿名函数(而不是作为回调)有何不同?换句话说,它与以下内容有何区别:

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

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

  notifier.notify({
    object: this,
    type: Thingy.INCREMENT,
    incremented: amount
  });
}
我已经看到,在最新的规范中,
notifier.performChange
可能会返回一个对象,然后作为通知发出,如下所示:

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

这消除了对以下通知程序的需要。在原始代码中通知,但是,这是不是除了糖之外的东西,或者这与仅仅进行更改并自己发出通知之间有功能上的区别?

经过一个小时的大量测试,我终于找到了答案。我有同样的问题(什么是
performChange
for?),也有同样的想法,就是脱下它打电话

this.a += amount;
this.b += amount;
但是,
通知程序.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's 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

我想为这个问题提供一个明确的答案,我也在问自己,所以我看了一下

以下是您需要了解的
Object.getNotifier(obj).performChange(changeType,changeFn)
的功能:

  • 它运行
    changeFn
  • 当运行
    changeFn
    时,它故意不通知任何观察者
    obj
  • 您可以进行
    changeFn
    返回一个对象:
    obj
    的观察者将收到该对象自身属性的通知
你自己看看,这是你在规范中寻找的

应用到您的示例中,这意味着这两种方法会导致完全相同的结果,但操作方式略有不同:

例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()
    将使用一个对象通知相应的观察者,该对象看起来与示例1中显式调用
    notify()
    得到的对象相同:
    {object:object,type:Thingy.INCREMENT,INCREMENT:amount}
这两个示例应该涵盖您希望使用
performChange()
的大多数情况,以及如何使用它。不过我会继续潜水,因为这只野兽的行为很有趣


不同步性 观察者是异步执行的。这意味着,上述示例中
increment()
函数内部发生的所有事情实际上都会在
increment()
执行完毕后报告给观察者,并且只有在执行完毕之后

换句话说,所有这些:

  • performChange()之外更改观察对象的属性
  • performChange()
    的回调中返回对象
  • 调用
    notify()
仅在
increment()
完成运行后通知相应的观察者

同步变更交付 如果您需要在执行
increment()
期间了解挂起的更改(挂起的更改=将在
increment()
结束时报告给观察者但尚未报告的所有更改),那么有一个解决方案:
Object.deliverChangeRecords(回调)

请注意,
callback
需要是对之前已注册为该对象的观察回调函数的引用

换句话说,这是行不通的:

(函数(){
var obj={prop:“a”};
观察对象(obj,功能(变化){
控制台日志(更改);
});
obj.prop=“b”;
对象。deliverChangeRecords(功能(更改){
控制台日志(更改);
});
控制台日志(“执行结束”);

})(); // Meh,我们在这里收到了变更通知,这不是我们想要的
关于一个相当模糊的主题的伟大而清晰的答案。它还阐明了类型在
performChange
中的作用。回答得好,但不幸的是第二个链接不起作用。@FabianLauer感谢您的提醒!我已经更新了链接:)
increment: function(amount) {
    var notifier = Object.getNotifier(this);

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

        return { incremented: amount };  
    });
}