2014-11-06 3 views
1

Изменения, массив из Object.observe() обратного вызова содержит объекты со следующими четырьмя свойствами:Почему Object.observe() не предоставляет путь передачи данных к обратному вызову?

  • имя
  • объект
  • типа
  • OldValue

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/observe#Parameters

Почему ISN» t есть a path предоставляется изначально? Пример:

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() также включать путь: observed.js,
, но я волнуюсь прирост производительности родной observe() будет потерян (если нет, то не могли бы вы объяснить, как это реализовано тогда?). Возможно, это будет browserify модуль, но он не может представить, что он будет хорошо работать в синхронной среде, и я все еще удивляюсь, почему никто, похоже, не подумал о дополнительном path.

ответ

6

Потому что нет четкого пути.

Рассмотрим следующий пример:

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 } } };      // nested objects 
notifySubobjectChanges(a);      // set up recursive observers 
Object.observe(a, console.log.bind(console)); // log changes to console 
a.a.b.c = 99; 

>> 0: Object 
    name: "c" 
    object: Object 
    oldValue: 1 
    path: "a.b"         // <=== here is your path! 
    type: "update" 

Приведенный выше код не является производство качественной, используйте на свой страх и риск.

+0

Хорошо, но как 'Object.observe()' ведет себя в конкретной ситуации, которую вы описали? Если два других объекта содержат первый объект, произойдет 3 изменения событий? Новый объект передается обратному вызову, поэтому наследование/вложение объектов не будет проблемой. BTW: «путь» не должен содержать «movall», «ob» или «ob2», но только следующее. В сочетании с переданным объектом, сменой 'type' и' oldValue', можно было бы непосредственно создать операцию OT. – CoDEmanX

+0

Изменение событий происходит, только если они наблюдаются, как дерево, падающее в лесу. Поэтому, если мы также наблюдаем «ob2», то да, другое событие изменения будет отправлено этому наблюдателю. –

+0

Просто уточнить: если мы наблюдаем 'movall' и' ob2', 'ob2' содержит' movall', и я делаю замену на 'ob2' -' ob2.b.movall.moo = "foo" '- будет там быть одним событием смены для «movall» и «ob2»? Если да, то нет никакой двусмысленности пути, поскольку это было бы относительно объекта, который мы наблюдаем, независимо от вложенных объектов ('moo' для' movall' и 'b.movall.moo' для' ob2'). – CoDEmanX