观察无法使用代理修改的对象



我想使用Proxies观察一个对象,这个对象来自我没有制作的游戏。我发现这是另一个问题的答案:

var proxied = new Proxy(foo, {
get: function(target, prop) {
console.log({
type: "get",
target,
prop
})
return Reflect.get(target, prop)
},
set: function(target, prop, value) {
console.log({
type: "set",
target,
prop,
value
})
return Reflect.set(target, prop, value)
}
})

如果我更改它,我必须执行proxied.bar = "Hello world"。但我不会改变,游戏会改变;它并不是这样做的。(它是foo.bar=…,他们不使用proxyed…)那么,我该怎么观察数组呢?谢谢

没有太多选项可以观察对象是否发生了更改。以前我们可以使用Object.observe()Object.watch(),但这两种方法都已被弃用,不再可靠。

代理是唯一的选择,但显然游戏必须使用代理对象才能击中陷阱。

我不完全知道在操作原始foo对象方面能做什么,但不要创建proxied对象,而是将foo设置为指向它自己的代理自身。换句话说,

foo = new Proxy(foo, {
get: function(target, prop) {
console.log({
type: "get",
target,
prop
})
return Reflect.get(target, prop)
},
set: function(target, prop, value) {
console.log({
type: "set",
target,
prop,
value
})
return Reflect.set(target, prop, value)
}
})

如果你可以像这样直接操作游戏的对象,那么在getset陷阱中,你可以传入自己的回调函数,并能够观察到该对象的任何变化。

您可能无法重新分配foo(如果它是用const声明的)。在这种情况下,有一个变通办法,但它有点笨拙,不像上面的方法那样同步。

本质上,您可以创建一个函数,在foo对象中创建条目缓存,并在给定的时间间隔重新检查foo是否有任何更改,并执行您指定的任何回调逻辑。我不能太具体,因为实现细节实际上依赖于foo的结构(,例如,它的嵌套性以及它可能包含的对象类型——无论是日期、函数引用还是许多其他类型的对象)。

一个基本的实现可能是这样的:

foo = { ... } // whatever kind of object foo is
function observeFoo() {
const entries = Object.entries(foo);
// initialize cache if we don't have one
if (!observeFoo.cache) observeFoo.cache = {};
// begin checking keys in cache
entries.forEach(entry => {
const [ key, value ] = entry;
if (observeFoo.cache[key] !== value) {
// do something regarding this change
}
// update cache
observeFoo.cache[key] = value;
});
}
setInterval(observeFoo, 1000);

最新更新