在 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',依次在 shallow
和 deep
上,这两个操作都被推送到一个数组中,作为在链条,例如:
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']
我不确定这是否是最佳解决方案,但它确实有效。尽管我仍然希望看到任何其他实现方法。
感谢大家的帮助。
我有一个 ES6 代理,其中包含其他深度嵌套的代理(在根代理的 get 陷阱中生成)。它们都使用相同的陷阱处理程序。
当我尝试获取此集合中深层嵌套对象的值时,会为遇到的每个深层嵌套对象调用 getter。必须在get序列完成后才能知道这个所谓的'path'通过对象的记录。例如调用:
console.log(proxy.shallow.deep);
是两个 get 操作的 'chain',依次在 shallow
和 deep
上,这两个操作都被推送到一个数组中,作为在链条,例如:
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']
我不确定这是否是最佳解决方案,但它确实有效。尽管我仍然希望看到任何其他实现方法。
感谢大家的帮助。