Почему Object.observe() не предоставляет путь изменения данных для обратного вызова?
Изменения массива Object.observe()
обратный вызов содержит объекты со следующими четырьмя свойствами:
- название
- объект
- тип
- OldValue
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/observe
Почему нет 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()
также включить путь: seen.js,
но я переживаю за прирост производительности родного observe()
будет потеряно (если нет, не могли бы вы объяснить, как это реализовано?). Возможно, модуль можно будет просмотреть, но не могу представить, что он будет работать хорошо в синхронной среде, и я все еще удивляюсь, почему, кажется, никто не задумывался о дополнительном path
имущество.
1 ответ
Потому что нет четкого пути.
Учтите следующее:
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"
Приведенный выше код не является производственным качеством, используйте его на свой страх и риск.