观察对象上的所有属性,包括稍后创建的属性

时间:2018-04-12 14:39:47

标签: javascript reflection metaprogramming handler defineproperty

假设我有一个对象var obj = {}。我希望稍后调用一个处理程序,检索任何字段; obj.b

我知道代理,

var obj = {};
var proxy = new Proxy(obj, {
  get(obj, prop) {
    console.log('get', prop)
    return Reflect.get(obj, prop);
  }
})

但是,这只会在通过代理proxy.b访问属性时记录,否则将无法记录obj.b

我也知道使用defineProperty将getter放在obj的所有键上。但是,这将不会处理添加getter后添加到obj的新字段。

也许如果可以重新实现代理,那么应该可以将处理程序添加到原始obj而不是proxy。我已经尝试过调查代理对象,但它似乎是在内部实现的。 new Proxy({},{})包含属性[[Handler]][[Target]][[IsRevoked]],但我无法访问或查看这些对象; proxy['[[Handler]]']返回undefined。我在想是否可以将这些处理程序和目标字段自己添加到obj,而不是创建单独的代理对象,然后我可以使obj像代理一样。

我已经阅读了MDN的代理,defineProperty和处理程序的文档,甚至是http://exploringjs.com/es6/ch_proxies.html。我同样遇到了多个堆栈溢出帖子,实现了类似但不完全的东西。

---编辑,我的用例(如果这比我的目标解决方案更清晰)---

我正在将source对象绑定到dom elmenets。例如,您更改source.text,并且dom上的一些文本也会更改。为此,source是一个代理,带有一个set handler来适当地更新dom。但是,要允许源上的嵌套字段,我必须在source.obj.text更改时进行处理。为此,我的源代理也有一个get hander,它也返回一个具有类似set和get处理程序的代理。以下代码段:

let createProxy = (obj, handlers) => new Proxy(obj, {
    get: (target, prop) => {
        let got = Reflect.get(target, prop);
        return typeof got === 'object' && got !== null ? createProxy(got, handlers && handlers[prop]) : got;
    },
    set: (target, prop, value) => {
        if (Reflect.get(target, prop) !== value) {
            Reflect.set(target, prop, value);

            handlers && propogateHandlerDown(handlers);
        }
        return true;
    }
});

这由let source = createProxy({}, ...)在内部使用,然后用户返回source。这通常很好。当用户不使用源时,问题就出现了,例如

let obj = {};
source.list = [obj];
source.list[0].text = 'this works fine';
obj.text = 'this does not work, as obj is not a proxy';

0 个答案:

没有答案