Javascript 为什么Object.observe()不提供回调更改的数据路径?

Javascript 为什么Object.observe()不提供回调更改的数据路径?,javascript,observers,ecmascript-harmony,object.observe,Javascript,Observers,Ecmascript Harmony,Object.observe,对象的changes数组。observe()回调包含具有以下四个属性的对象: 名字 反对 类型 旧价值 为什么没有本机提供的路径?例如: var ob = { foo: [ {moo: "bar", val: 5}, {val: 8} ] } ob.foo[0].val = 1; // callback should provide path "foo.0.val" or "foo[0].val" 有一个Node.js模块扩展了Objec

对象的changes数组。observe()
回调包含具有以下四个属性的对象:

  • 名字
  • 反对
  • 类型
  • 旧价值

为什么没有本机提供的
路径
?例如:

var ob = {
    foo: [
        {moo: "bar", val: 5},
        {val: 8}
    ]
}

ob.foo[0].val = 1;
// callback should provide path "foo.0.val" or "foo[0].val"
有一个Node.js模块扩展了
Object.observe()
,还包括路径:,

但是我担心本机
observe()
的性能增益会丢失(如果没有,请解释一下它是如何实现的?)。这个模块可能是可以实现的,但无法想象它在同步环境中会有良好的性能,我仍然想知道为什么似乎没有人考虑过额外的
路径
属性。

因为没有清晰的路径

考虑以下几点:

var movall = {moo: "bar", val: 5};
var ob1    = {a: mooval};
var ob2    = {b: movall};
现在让我们假设我观察
movall
。然后我更新
moo
。这条路是什么?它是
movall.moo
,还是
ob1.a.moo
,还是
ob2.b.moo
?如果我观察到
ob1
,则没有报告任何更改,因为它的任何属性都没有更改(更改是它的一个属性的内部更改,不计算在内)

对象独立于嵌套在其他对象中的对象的存在。它们可以嵌套在多个其他对象中。没有唯一的“路径”来描述如何从潜在的多个起点到可能已更改的特定属性

JS也不知道您到达正在更改的属性的路径。所以在
ob.foo[0].val=1,JS只是计算链,到达
foo[0]
对象,更改其
val
属性,此时不知道它是如何到达
foo[0]
的。它只知道
foo[0]
已经改变了。它在
ob
中发生了更改,但它也可能在碰巧具有
foo[0]
属性的其他对象中发生了更改

然而,通过在低级的观察/通知机制之上构建一些机制,您可能会实现您似乎想要实现的目标。我们将在对象上定义一个函数,该函数在其属性对象上设置观察者,以此类推,并使用正确构造的路径传播更改记录:

function notifySubobjectChanges(object) {
  var notifier = Object.getNotifier(object);        // get notifier for this object
  for (var k in object) {                           // loop over its properties
    var prop = object[k];                           // get property value
    if (!prop || typeof prop !== 'object') break;   // skip over non-objects
    Object.observe(prop, function(changes) {        // observe the property value
      changes.forEach(function(change) {            // and for each change
        notifier.notify({                           // notify parent object
          object: change.object,                    // with a modified changerec
          name: change.name,                        // which is basically the same
          type: change.type, 
          oldValue: change.oldValue, 
          path: k + 
            (change.path ? '.' + change.path : '')  // but has an addt'l path property
        });
      });
    });
    notifySubobjectChanges(prop);                   // repeat for sub-subproperties
  }
}
(注意:
change
对象已冻结,我们无法向其添加任何内容,因此必须复制它。)

现在

a={a:{b:{c:1}}};//嵌套对象
notifySubobjectChanges(a);//设置递归观察器
Object.observe(a,console.log.bind(console));//将更改记录到控制台
a、 a.b.c=99;
>>0:对象
名称:“c”
对象:对象
旧值:1

路径:“a.b”/,因为没有清晰的路径

考虑以下几点:

var movall = {moo: "bar", val: 5};
var ob1    = {a: mooval};
var ob2    = {b: movall};
现在让我们假设我观察
movall
。然后我更新
moo
。这条路是什么?它是
movall.moo
,还是
ob1.a.moo
,还是
ob2.b.moo
?如果我观察到
ob1
,则没有报告任何更改,因为它的任何属性都没有更改(更改是它的一个属性的内部更改,不计算在内)

对象独立于嵌套在其他对象中的对象的存在。它们可以嵌套在多个其他对象中。没有唯一的“路径”来描述如何从潜在的多个起点到可能已更改的特定属性

JS也不知道您到达正在更改的属性的路径。所以在
ob.foo[0].val=1,JS只是计算链,到达
foo[0]
对象,更改其
val
属性,此时不知道它是如何到达
foo[0]
的。它只知道
foo[0]
已经改变了。它在
ob
中发生了更改,但它也可能在碰巧具有
foo[0]
属性的其他对象中发生了更改

然而,通过在低级的观察/通知机制之上构建一些机制,您可能会实现您似乎想要实现的目标。我们将在对象上定义一个函数,该函数在其属性对象上设置观察者,以此类推,并使用正确构造的路径传播更改记录:

function notifySubobjectChanges(object) {
  var notifier = Object.getNotifier(object);        // get notifier for this object
  for (var k in object) {                           // loop over its properties
    var prop = object[k];                           // get property value
    if (!prop || typeof prop !== 'object') break;   // skip over non-objects
    Object.observe(prop, function(changes) {        // observe the property value
      changes.forEach(function(change) {            // and for each change
        notifier.notify({                           // notify parent object
          object: change.object,                    // with a modified changerec
          name: change.name,                        // which is basically the same
          type: change.type, 
          oldValue: change.oldValue, 
          path: k + 
            (change.path ? '.' + change.path : '')  // but has an addt'l path property
        });
      });
    });
    notifySubobjectChanges(prop);                   // repeat for sub-subproperties
  }
}
(注意:
change
对象已冻结,我们无法向其添加任何内容,因此必须复制它。)

现在

a={a:{b:{c:1}}};//嵌套对象
notifySubobjectChanges(a);//设置递归观察器
Object.observe(a,console.log.bind(console));//将更改记录到控制台
a、 a.b.c=99;
>>0:对象
名称:“c”
对象:对象
旧值:1

路径:“a.b”//很好,但是
Object.observe()
在您描述的确切情况下是如何工作的?如果其他两个对象包含第一个对象,是否会发生3个更改事件?新对象被传递给回调,因此继承/对象嵌套不会成为问题。顺便说一句:
路径
不应包含
movall
ob
ob2
,而只应包含以下内容。结合传递的对象,更改
类型
旧值
,可以直接创建一个OT操作。只有在观察到更改事件时,更改事件才会“发生”,如森林中的树木倒下。因此,如果我们也观察到
ob2
,那么是的,另一个更改事件将发送给该观察者。只是为了澄清:如果我们观察到
movall
ob2
ob2
包含
movall
,我对
ob2
-
ob2.b.moball.foo=“foo”
-是否会有一个到
movall
的更改事件和一个到
ob2
的更改事件?如果是,那么就没有路径模糊性,因为它与我们观察到的对象相关,而与嵌套对象无关(