如何创build一个深度代理?

我如何创build一个深度/recursion的代理 ?

具体来说,我想知道每当一个属性被设置或修改在对象树中的任何地方。

这是迄今为止我所得到的:

function deepProxy(obj) { return new Proxy(obj, { set(target, property, value, receiver) { console.log('set', property,'=', value); if(typeof value === 'object') { for(let k of Object.keys(value)) { if(typeof value[k] === 'object') { value[k] = deepProxy(value[k]); } } value = deepProxy(value); } target[property] = value; return true; }, deleteProperty(target, property) { if(Reflect.has(target, property)) { let deleted = Reflect.deleteProperty(target, property); if(deleted) { console.log('delete', property); } return deleted; } return false; } }); } 

这是我的testing:

 const proxy = deepProxy({}); const baz = {baz: 9, quux: {duck: 6}}; proxy.foo = 5; proxy.bar = baz; proxy.bar.baz = 10; proxy.bar.quux.duck = 999; baz.quux.duck = 777; delete proxy.bar; delete proxy.bar; // should not trigger notifcation -- property was already deleted baz.quux.duck = 666; // should not trigger notification -- 'bar' was detached console.log(proxy); 

而输出:

 set foo = 5 set bar = { baz: 9, quux: { duck: 6 } } set baz = 10 set duck = 999 set duck = 777 delete bar set duck = 666 { foo: 5 } 

正如你所看到的,我只是把它工作,除了baz.quux.duck = 666即使我已经从proxy的对象树中删除它触发setter。 在物业被删除之后,有没有什么办法可以解除巴兹?

修复了我原来的问题中的一堆错误。 我认为这现在有效:

 function createDeepProxy(target, handler) { const preproxy = new WeakMap(); function makeHandler(path) { return { set(target, key, value, receiver) { if(typeof value === 'object') { value = proxify(value, [...path, key]); } target[key] = value; if(handler.set) { handler.set(target, [...path, key], value, receiver); } return true; }, deleteProperty(target, key) { if(Reflect.has(target, key)) { unproxy(target, key); let deleted = Reflect.deleteProperty(target, key); if(deleted && handler.deleteProperty) { handler.deleteProperty(target, [...path, key]); } return deleted; } return false; } } } function unproxy(obj, key) { if(preproxy.has(obj[key])) { // console.log('unproxy',key); obj[key] = preproxy.get(obj[key]); preproxy.delete(obj[key]); } for(let k of Object.keys(obj[key])) { if(typeof obj[key][k] === 'object') { unproxy(obj[key], k); } } } function proxify(obj, path) { for(let key of Object.keys(obj)) { if(typeof obj[key] === 'object') { obj[key] = proxify(obj[key], [...path, key]); } } let p = new Proxy(obj, makeHandler(path)); preproxy.set(p, obj); return p; } return proxify(target, []); } module.exports = createDeepProxy; 

用法:

 let proxied = createDeepProxy(obj, { set(target, path, value, receiver) { console.log(Chalk.green('set'), path.join('.'), Chalk.dim('='), inspect(value)); }, deleteProperty(target, path) { console.log(Chalk.red('delete'), path.join('.')); } }); proxied.foo = 'bar'; // will trigger `set` delete proxified.foo; // will trigger `deleteProperty` 

您可以将完整的对象分配给属性,并且它们将被recursion地代入,然后当您将它们从代理对象中删除时,它们将被取消,以便您不会收到不再是对象的一部分的对象的通知,graphics。

我不知道如果你创build一个循环链接会发生什么。 我不推荐它。