Mat*_*ert 17 javascript proxy-object
我将一个对象包装在一个代理中,然后迭代它.如何控制它迭代的键?
如果我不覆盖键,代理可以工作:
var obj = {"hello": "world"}
var proxy = new Proxy(obj, {})
for (var key in proxy){
console.log(key)
}
// logs "Hello"
Run Code Online (Sandbox Code Playgroud)
但是,如果我更改ownKeys处理程序中的键,则不记录任何内容.
var obj = {"hello": "world"}
var proxy = new Proxy(obj, {
ownKeys: function(){
return ["a", "b"]
}
})
for (var key in proxy){
console.log(key)
}
// Logs nothing
Run Code Online (Sandbox Code Playgroud)
如果我返回"hello"作为ownKeys唯一"hello"记录的一部分.
显然enumerateES6中有陷阱,但它已从ES7中删除.
是否仍然可以for...in使用代理控制循环?为什么enumerate从规范中删除了?
不幸的是,不可能再这样做了.
正如Brian Terlson(EcmaScript规范的编辑)写道:
代理枚举陷阱和for-in的问题,其中禁止实现预先填充对象中的键列表,因为迭代器会导致可观察到的影响.这意味着必须为每次迭代提取迭代次数.上次会议我们认为如果枚举陷阱耗尽迭代器就好了,我们认为这样可以解决问题.问题是,现在它们是该对象的对象和代理之间的可观察差异,主要是由于删除.
(来源:https://github.com/rwaldron/tc39-notes/blob/master/es7/2016-01/2016-01-28.md#5xix-proxy-enumerate---revisit-decision-to-exhaust -迭代器经由https://ecmascript-daily.github.io/2016/02/10/why-remove-enumerate-and-reflect-enumerate)
因此,由于无法以令人满意的方式解决的技术挑战,它被删除了.
有代理陷阱
in仍然可以使用has代理陷阱捕获这样的运算符:
var p = new Proxy({}, {
has: function(target, prop) {
if (prop === 'a') { return true; }
return false;
}
});
'a' in p; // true
'b' in p; // false
Run Code Online (Sandbox Code Playgroud)
替代
由于for (let key in proxy)循环现在更像是一项遗留功能,您可以使用以下其中一项ownKeys代理陷阱:
Object.keys() (仅限自己的可枚举属性)Object.getOwnPropertyNames() (自己的房产)Reflect.ownKeys() (自己的属性和符号)
(来源:https://twitter.com/nilssolanki/status/659839340592422912)
(但你可能已经知道,首先看到你正在使用代理)
用户 user2106769 的建议和 yeerk 的重写 getOwnPropertyDescriptor 以允许枚举代理属性的答案有一个缺陷,在使用它时应该注意,它在捕获 getOwnPropertyDescriptor 时不会设置 value 属性,因此一些其他代码依赖于该行为将无法正常工作。
演示该缺陷的代码及其解决方案如下:
var obj = { "hello": "world" };
var flawedProxy = new Proxy(obj, {
ownKeys: function() {
return ["a", "b"];
},
getOwnPropertyDescriptor: function(target, key) {
return { enumerable: true, configurable: true };
}
});
var goodProxy = new Proxy(obj, {
get: function(target, key) {
// modify something here if you want to
return target[key];
},
ownKeys: function() {
return ["a", "b"];
},
getOwnPropertyDescriptor: function(target, key) {
return { value: this.get(target, key), enumerable: true, configurable: true };
}
});
// value is accessible, getOwnPropertyDescriptor not trapped
console.log(Object.getOwnPropertyDescriptor(obj, 'hello').value);
// value is undefined, getOwnPropertyDescriptor not trapped correctly
console.log(Object.getOwnPropertyDescriptor(flawedProxy, 'hello').value);
// value is accessible, getOwnPropertyDescriptor trapped correctly
console.log(Object.getOwnPropertyDescriptor(goodProxy, 'hello').value);Run Code Online (Sandbox Code Playgroud)
user2106769 给出了解决方案作为评论,但对于像我这样没有看到他们评论的其他人,您可以for..in使用ownKeysand覆盖迭代getOwnPropertyDescriptor:
var obj = { "hello": "world" };
var proxy = new Proxy(obj, {
ownKeys: function() {
return ["a", "b"];
},
getOwnPropertyDescriptor: function(target, key) {
return { enumerable: true, configurable: true };
}
});
for (var key in proxy) {
console.log(key);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1242 次 |
| 最近记录: |