【问题标题】:Why isn't ownKeys Proxy trap working with Object.keys()?为什么 ownKeys 代理陷阱不能与 Object.keys() 一起使用?
【发布时间】:2021-03-28 02:25:31
【问题描述】:
在documentation of the Proxy ownKeys trap on MDN 中声明它将拦截Object.keys() 调用:
这个陷阱可以拦截这些操作:
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
Reflect.ownKeys()
但是,从我的测试来看,它似乎不适用于Object.keys:
const proxy = new Proxy({}, {
ownKeys() {
console.log("called")
return ["a", "b", "c"]
}
})
console.log(Object.keys(proxy))
console.log(Object.getOwnPropertyNames(proxy))
console.log(Reflect.ownKeys(proxy))
是 MDN 错了,还是我做错了什么?
【问题讨论】:
标签:
javascript
ecmascript-6
es6-proxy
【解决方案1】:
原因很简单:Object.keys 只返回带有可枚举标志的属性。为了检查它,它为每个属性调用内部方法[[GetOwnProperty]] 以获取其描述符。而这里,由于没有属性,它的描述符是空的,没有可枚举的标志,所以它被跳过了。
为了让Object.keys 返回一个属性,我们需要它存在于对象中,带有可枚举标志,或者我们可以拦截对 [[GetOwnProperty]] 的调用(陷阱 getOwnPropertyDescriptor 执行此操作),并返回一个描述符可枚举:true。
这是一个例子:
let user = { };
user = new Proxy(user, {
ownKeys(target) { // called once to get a list of properties
return ['a', 'b', 'c'];
},
getOwnPropertyDescriptor(target, prop) { // called for every property
return {
enumerable: true,
configurable: true
/* ...other flags, probable "value:..." */
};
}
});
console.log( Object.keys(user) ); // ['a', 'b', 'c']
Source
【解决方案2】:
Object.keys 仅返回对象的 可枚举 自身属性。您的代理没有这样的,或者至少它没有在其getOwnPropertyDescriptor 陷阱中报告它们。它适用于
const proxy = new Proxy({}, {
ownKeys() {
console.log("called ownKeys")
return ["a", "b", "c"]
},
getOwnPropertyDescriptor(target, prop) {
console.log(`called getOwnPropertyDescriptor(${prop})`);
return { configurable: true, enumerable: true };
}
})
console.log(Object.keys(proxy))
console.log(Object.getOwnPropertyNames(proxy))
console.log(Reflect.ownKeys(proxy))