在 ES6 代理完成其 'gets' 序列后执行函数?

Execute a function after an ES6 Proxy has completed its sequence of 'gets'?

我有一个 ES6 代理,其中包含其他深度嵌套的代理(在根代理的 get 陷阱中生成)。它们都使用相同的陷阱处理程序。

当我尝试获取此集合中深层嵌套对象的值时,会为遇到的每个深层嵌套对象调用 getter。必须在get序列完成后才能知道这个所谓的'path'通过对象的记录。例如调用:

console.log(proxy.shallow.deep);

是两个 get 操作的 'chain',依次在 shallowdeep 上,这两个操作都被推送到一个数组中,作为在链条,例如:

console.log(path); // ['shallow', 'deep']

不过这有一个问题。在任何 get 序列中,不可能知道链中的最终 get 是什么——每次到代理的 get 都被视为一个原子操作,因此没有内在的概念 属性 是最后一个被调用的.这意味着在随后的 'get chains' 中,path 数组已经具有与之关联的值。我在下面写了一些代码来说明我的代理的结构和我遇到的问题:

let nestedObject = { shallow: { deep: 0 }};
let path = [];
let proxy = new Proxy(nestedObject, {
    get(target, prop) {
        path.push(prop);
        let out = target[prop];
        // this ensures each get to the proxy (whenever the value at property 
        // is an object), returns that object as a new proxy, 
        // else return the value of the property
        // this means the get/set traps are called for each deeply nested object
        return typeof out === 'object' ? new Proxy(out, this) : out;
    },
    set(target, prop, val) {
        path.push(prop);
        target[prop] = val;
        path.length = 0;
    }
});

// getting these two pushes both properties to the path array
// but there's no way of knowing that the get to 'deep' was the final 
// get in the chain - therefore it cannot be reset for the next get chain
proxy.shallow.deep;
// path: ['shallow', 'deep']
console.log(path);

// because of this, I can't figure out how the code should know that the path
// array must be reset - so subsequent gets just add more values to the path array,
// and there are erroneous elements in the array when the next chain starts
proxy.shallow.deep
// path: ['shallow', 'deep', 'shallow', 'deep']
console.log(path);

// setting a value is fine however, since a set action will always be the last action
// it pushes 'shallow' to the array in the getter and 'deep' in setter. 
// The setter can then clear the path array.
proxy.shallow.deep = 1;
// path: []
console.log(path);

所以我想知道的是:是否有可能以某种方式知道链中的最后一个 'get' 是什么,and/or 如果有办法调用每当获取链完成时函数?

感谢您的帮助!

我想我已经找到了一个对我来说合理的解决方案,它只需要对代码进行很少的更改。它涉及将路径变量附加到每个后续的陷阱处理程序,其值是每个先前处理程序的路径值的累加值。像这样:

let nestedObject = { shallow: { deep: {deepest: 0 }}};
let path = [];
let proxy = new Proxy(nestedObject, {
    get(target, prop) {
        let out = target[prop];
        // make a copy of this handler for the nested proxy to use
        let copy = Object.assign({}, this);
        // if this handler contains no path variable, add it
        // otherwise concatenate it with the previous handler's path 
        !this.path ?
            Object.assign(copy, {path: [prop]}) :
            Object.assign(copy, {path: this.path.concat(prop)});
        path = copy.path;
        return typeof out === 'object' ?
            new Proxy(out, copy) :
            out;
    },
    set(target, prop, val) {
        path = this.path.concat(prop);
        target[prop] = val;
    }
});

proxy.shallow;
console.log(path); // ['shallow']
proxy.shallow.deep;
console.log(path); // ['shallow', 'deep']
proxy.shallow.deep.deepest;
console.log(path); // ['shallow', 'deep', 'deepest']
proxy.shallow.deep.deepest = 1;
console.log(path); // ['shallow', 'deep', 'deepest']

我不确定这是否是最佳解决方案,但它确实有效。尽管我仍然希望看到任何其他实现方法。

感谢大家的帮助。