sdg*_*uck 8 javascript ecmascript-6 es6-proxy
在MDN 上的代理陷阱文档ownKeys中,它指出它将拦截Object.keys()调用:
该陷阱可以拦截以下操作:
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
对象.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))Run Code Online (Sandbox Code Playgroud)
原因很简单:Object.keys仅返回带有可枚举标志的属性。为了检查它,它调用[[GetOwnProperty]]每个属性的内部方法来获取其描述符。而这里,由于\xe2\x80\x99s没有属性,它的描述符为空,没有可枚举标志,所以它\xe2\x80\x99s被跳过。
为了Object.keys返回一个属性,我们需要它存在于对象中,并带有可枚举标志,或者我们可以拦截对 [[GetOwnProperty]] 的调用(陷阱 getOwnPropertyDescriptor 可以做到这一点),并返回一个带有 enumerable: true 的描述符。
这里\xe2\x80\x99s 是一个例子:
\nlet user = { };\n\nuser = new Proxy(user, {\n ownKeys(target) { // called once to get a list of properties\n return [\'a\', \'b\', \'c\'];\n },\n\n getOwnPropertyDescriptor(target, prop) { // called for every property\n return {\n enumerable: true,\n configurable: true\n /* ...other flags, probable "value:..." */\n };\n }\n\n});\n\nconsole.log( Object.keys(user) ); // [\'a\', \'b\', \'c\']Run Code Online (Sandbox Code Playgroud)\r\n